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", "1", "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_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
38 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
39 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)"};
40 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
41 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
42 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"};
43 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"};
44 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
45 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"};
46 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"};
47 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"};
48 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
49 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
50 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
51 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
52 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
53 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
54 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
55 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
56 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
57 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
58 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
59 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
60 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
61 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
62 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
63 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"};
64 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"};
65 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 gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
74 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
76 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)"};
78 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
79 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)"};
80 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)"};
81 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
82 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
83 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
84 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
85 cvar_t r_glsl_postprocess_contrastboost = {CVAR_SAVE, "r_glsl_postprocess_contrastboost", "1", "brightening effect (1 is no change, higher values brighten the view)"};
86 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)"};
88 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)"};
89 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
90 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"};
91 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
92 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
94 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
95 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
96 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
97 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
99 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
100 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
101 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
102 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
103 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
104 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
105 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
107 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
108 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
109 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
110 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)"};
112 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"};
114 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"};
116 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
118 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
119 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
120 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"};
121 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
122 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
123 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
125 extern qboolean v_flipped_state;
127 static struct r_bloomstate_s
132 int bloomwidth, bloomheight;
134 int screentexturewidth, screentextureheight;
135 rtexture_t *texture_screen;
137 int bloomtexturewidth, bloomtextureheight;
138 rtexture_t *texture_bloom;
140 // arrays for rendering the screen passes
141 float screentexcoord2f[8];
142 float bloomtexcoord2f[8];
143 float offsettexcoord2f[8];
147 typedef struct r_waterstate_waterplane_s
149 rtexture_t *texture_refraction;
150 rtexture_t *texture_reflection;
152 int materialflags; // combined flags of all water surfaces on this plane
153 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
156 r_waterstate_waterplane_t;
158 #define MAX_WATERPLANES 16
160 static struct r_waterstate_s
164 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
166 int waterwidth, waterheight;
167 int texturewidth, textureheight;
169 int maxwaterplanes; // same as MAX_WATERPLANES
171 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
173 float screenscale[2];
174 float screencenter[2];
178 // shadow volume bsp struct with automatically growing nodes buffer
181 rtexture_t *r_texture_blanknormalmap;
182 rtexture_t *r_texture_white;
183 rtexture_t *r_texture_grey128;
184 rtexture_t *r_texture_black;
185 rtexture_t *r_texture_notexture;
186 rtexture_t *r_texture_whitecube;
187 rtexture_t *r_texture_normalizationcube;
188 rtexture_t *r_texture_fogattenuation;
189 //rtexture_t *r_texture_fogintensity;
191 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
192 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
194 // vertex coordinates for a quad that covers the screen exactly
195 const static float r_screenvertex3f[12] =
203 extern void R_DrawModelShadows(void);
205 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
208 for (i = 0;i < verts;i++)
219 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
222 for (i = 0;i < verts;i++)
232 // FIXME: move this to client?
235 if (gamemode == GAME_NEHAHRA)
237 Cvar_Set("gl_fogenable", "0");
238 Cvar_Set("gl_fogdensity", "0.2");
239 Cvar_Set("gl_fogred", "0.3");
240 Cvar_Set("gl_foggreen", "0.3");
241 Cvar_Set("gl_fogblue", "0.3");
243 r_refdef.fog_density = 0;
244 r_refdef.fog_red = 0;
245 r_refdef.fog_green = 0;
246 r_refdef.fog_blue = 0;
247 r_refdef.fog_alpha = 1;
248 r_refdef.fog_start = 0;
249 r_refdef.fog_end = 0;
252 float FogForDistance(vec_t dist)
254 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
255 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
258 float FogPoint_World(const vec3_t p)
260 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
263 float FogPoint_Model(const vec3_t p)
265 return FogForDistance(VectorDistance((p), rsurface.modelorg));
268 static void R_BuildBlankTextures(void)
270 unsigned char data[4];
271 data[2] = 128; // normal X
272 data[1] = 128; // normal Y
273 data[0] = 255; // normal Z
274 data[3] = 128; // height
275 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
280 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
285 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
290 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
293 static void R_BuildNoTexture(void)
296 unsigned char pix[16][16][4];
297 // this makes a light grey/dark grey checkerboard texture
298 for (y = 0;y < 16;y++)
300 for (x = 0;x < 16;x++)
302 if ((y < 8) ^ (x < 8))
318 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
321 static void R_BuildWhiteCube(void)
323 unsigned char data[6*1*1*4];
324 memset(data, 255, sizeof(data));
325 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
328 static void R_BuildNormalizationCube(void)
332 vec_t s, t, intensity;
334 unsigned char data[6][NORMSIZE][NORMSIZE][4];
335 for (side = 0;side < 6;side++)
337 for (y = 0;y < NORMSIZE;y++)
339 for (x = 0;x < NORMSIZE;x++)
341 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
342 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
377 intensity = 127.0f / sqrt(DotProduct(v, v));
378 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
379 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
380 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
381 data[side][y][x][3] = 255;
385 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
388 static void R_BuildFogTexture(void)
392 unsigned char data1[FOGWIDTH][4];
393 //unsigned char data2[FOGWIDTH][4];
396 r_refdef.fogmasktable_start = r_refdef.fog_start;
397 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
398 r_refdef.fogmasktable_range = r_refdef.fogrange;
399 r_refdef.fogmasktable_density = r_refdef.fog_density;
401 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
402 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
404 d = (x * r - r_refdef.fogmasktable_start);
405 if(developer.integer >= 100)
406 Con_Printf("%f ", d);
408 if (r_fog_exp2.integer)
409 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
411 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
412 if(developer.integer >= 100)
413 Con_Printf(" : %f ", alpha);
414 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
415 if(developer.integer >= 100)
416 Con_Printf(" = %f\n", alpha);
417 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
420 for (x = 0;x < FOGWIDTH;x++)
422 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
427 //data2[x][0] = 255 - b;
428 //data2[x][1] = 255 - b;
429 //data2[x][2] = 255 - b;
432 if (r_texture_fogattenuation)
434 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
435 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
439 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);
440 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
444 static const char *builtinshaderstring =
445 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
446 "// written by Forest 'LordHavoc' Hale\n"
448 "// common definitions between vertex shader and fragment shader:\n"
450 "//#ifdef __GLSL_CG_DATA_TYPES\n"
451 "//# define myhalf half\n"
452 "//# define myhalf2 half2\n"
453 "//# define myhalf3 half3\n"
454 "//# define myhalf4 half4\n"
456 "# define myhalf float\n"
457 "# define myhalf2 vec2\n"
458 "# define myhalf3 vec3\n"
459 "# define myhalf4 vec4\n"
462 "#ifdef MODE_DEPTH_OR_SHADOW\n"
464 "# ifdef VERTEX_SHADER\n"
467 " gl_Position = ftransform();\n"
473 "#ifdef MODE_POSTPROCESS\n"
474 "# ifdef VERTEX_SHADER\n"
477 " gl_FrontColor = gl_Color;\n"
478 " gl_Position = ftransform();\n"
479 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
481 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
485 "# ifdef FRAGMENT_SHADER\n"
487 "uniform sampler2D Texture_First;\n"
489 "uniform sampler2D Texture_Second;\n"
491 "#ifdef USEVERTEXTEXTUREBLEND\n"
492 "uniform vec4 TintColor;\n"
494 "#ifdef USECOLORMOD\n"
495 "uniform vec3 Gamma;\n"
497 "#ifdef USECONTRASTBOOST\n"
498 "uniform float ContrastBoostCoeff;\n"
502 " gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
504 " gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
506 "#ifdef USECONTRASTBOOST\n"
507 " gl_FragColor.rgb /= (ContrastBoostCoeff * gl_FragColor.rgb + vec3(1.0, 1.0, 1.0));\n"
508 " gl_FragColor.rgb *= (ContrastBoostCoeff + 1.0);\n"
510 "#ifdef USEVERTEXTEXTUREBLEND\n"
511 " gl_FragColor = mix(TintColor, gl_FragColor, TintColor.a);\n"
519 "#ifdef MODE_GENERIC\n"
520 "# ifdef VERTEX_SHADER\n"
523 " gl_FrontColor = gl_Color;\n"
524 "# ifdef USEDIFFUSE\n"
525 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
527 "# ifdef USESPECULAR\n"
528 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
530 " gl_Position = ftransform();\n"
533 "# ifdef FRAGMENT_SHADER\n"
535 "# ifdef USEDIFFUSE\n"
536 "uniform sampler2D Texture_First;\n"
538 "# ifdef USESPECULAR\n"
539 "uniform sampler2D Texture_Second;\n"
544 " gl_FragColor = gl_Color;\n"
545 "# ifdef USEDIFFUSE\n"
546 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
549 "# ifdef USESPECULAR\n"
550 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
552 "# ifdef USECOLORMAPPING\n"
553 " gl_FragColor *= tex2;\n"
556 " gl_FragColor += tex2;\n"
558 "# ifdef USEVERTEXTEXTUREBLEND\n"
559 " gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n"
564 "#else // !MODE_GENERIC\n"
566 "varying vec2 TexCoord;\n"
567 "varying vec2 TexCoordLightmap;\n"
569 "#ifdef MODE_LIGHTSOURCE\n"
570 "varying vec3 CubeVector;\n"
573 "#ifdef MODE_LIGHTSOURCE\n"
574 "varying vec3 LightVector;\n"
576 "#ifdef MODE_LIGHTDIRECTION\n"
577 "varying vec3 LightVector;\n"
580 "varying vec3 EyeVector;\n"
582 "varying vec3 EyeVectorModelSpace;\n"
585 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
586 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
587 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
589 "#ifdef MODE_WATER\n"
590 "varying vec4 ModelViewProjectionPosition;\n"
591 "#ifdef MODE_REFRACTION\n"
592 "varying vec4 ModelViewProjectionPosition;\n"
594 "# ifdef USEREFLECTION\n"
595 "varying vec4 ModelViewProjectionPosition;\n"
604 "// vertex shader specific:\n"
605 "#ifdef VERTEX_SHADER\n"
607 "uniform vec3 LightPosition;\n"
608 "uniform vec3 EyePosition;\n"
609 "uniform vec3 LightDir;\n"
611 "// 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"
615 " gl_FrontColor = gl_Color;\n"
616 " // copy the surface texcoord\n"
617 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
618 "#ifndef MODE_LIGHTSOURCE\n"
619 "# ifndef MODE_LIGHTDIRECTION\n"
620 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
624 "#ifdef MODE_LIGHTSOURCE\n"
625 " // transform vertex position into light attenuation/cubemap space\n"
626 " // (-1 to +1 across the light box)\n"
627 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
629 " // transform unnormalized light direction into tangent space\n"
630 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
631 " // normalize it per pixel)\n"
632 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
633 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
634 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
635 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
638 "#ifdef MODE_LIGHTDIRECTION\n"
639 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
640 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
641 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
644 " // transform unnormalized eye direction into tangent space\n"
646 " vec3 EyeVectorModelSpace;\n"
648 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
649 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
650 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
651 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
653 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
654 " VectorS = gl_MultiTexCoord1.xyz;\n"
655 " VectorT = gl_MultiTexCoord2.xyz;\n"
656 " VectorR = gl_MultiTexCoord3.xyz;\n"
659 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
660 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
661 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
662 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
665 "// transform vertex to camera space, using ftransform to match non-VS\n"
667 " gl_Position = ftransform();\n"
669 "#ifdef MODE_WATER\n"
670 " ModelViewProjectionPosition = gl_Position;\n"
672 "#ifdef MODE_REFRACTION\n"
673 " ModelViewProjectionPosition = gl_Position;\n"
675 "#ifdef USEREFLECTION\n"
676 " ModelViewProjectionPosition = gl_Position;\n"
680 "#endif // VERTEX_SHADER\n"
685 "// fragment shader specific:\n"
686 "#ifdef FRAGMENT_SHADER\n"
688 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
689 "uniform sampler2D Texture_Normal;\n"
690 "uniform sampler2D Texture_Color;\n"
691 "uniform sampler2D Texture_Gloss;\n"
692 "uniform sampler2D Texture_Glow;\n"
693 "uniform sampler2D Texture_SecondaryNormal;\n"
694 "uniform sampler2D Texture_SecondaryColor;\n"
695 "uniform sampler2D Texture_SecondaryGloss;\n"
696 "uniform sampler2D Texture_SecondaryGlow;\n"
697 "uniform sampler2D Texture_Pants;\n"
698 "uniform sampler2D Texture_Shirt;\n"
699 "uniform sampler2D Texture_FogMask;\n"
700 "uniform sampler2D Texture_Lightmap;\n"
701 "uniform sampler2D Texture_Deluxemap;\n"
702 "uniform sampler2D Texture_Refraction;\n"
703 "uniform sampler2D Texture_Reflection;\n"
704 "uniform sampler2D Texture_Attenuation;\n"
705 "uniform samplerCube Texture_Cube;\n"
707 "uniform myhalf3 LightColor;\n"
708 "uniform myhalf3 AmbientColor;\n"
709 "uniform myhalf3 DiffuseColor;\n"
710 "uniform myhalf3 SpecularColor;\n"
711 "uniform myhalf3 Color_Pants;\n"
712 "uniform myhalf3 Color_Shirt;\n"
713 "uniform myhalf3 FogColor;\n"
715 "uniform myhalf4 TintColor;\n"
718 "//#ifdef MODE_WATER\n"
719 "uniform vec4 DistortScaleRefractReflect;\n"
720 "uniform vec4 ScreenScaleRefractReflect;\n"
721 "uniform vec4 ScreenCenterRefractReflect;\n"
722 "uniform myhalf4 RefractColor;\n"
723 "uniform myhalf4 ReflectColor;\n"
724 "uniform myhalf ReflectFactor;\n"
725 "uniform myhalf ReflectOffset;\n"
727 "//# ifdef MODE_REFRACTION\n"
728 "//uniform vec4 DistortScaleRefractReflect;\n"
729 "//uniform vec4 ScreenScaleRefractReflect;\n"
730 "//uniform vec4 ScreenCenterRefractReflect;\n"
731 "//uniform myhalf4 RefractColor;\n"
732 "//# ifdef USEREFLECTION\n"
733 "//uniform myhalf4 ReflectColor;\n"
736 "//# ifdef USEREFLECTION\n"
737 "//uniform vec4 DistortScaleRefractReflect;\n"
738 "//uniform vec4 ScreenScaleRefractReflect;\n"
739 "//uniform vec4 ScreenCenterRefractReflect;\n"
740 "//uniform myhalf4 ReflectColor;\n"
745 "uniform myhalf GlowScale;\n"
746 "uniform myhalf SceneBrightness;\n"
747 "#ifdef USECONTRASTBOOST\n"
748 "uniform myhalf ContrastBoostCoeff;\n"
751 "uniform float OffsetMapping_Scale;\n"
752 "uniform float OffsetMapping_Bias;\n"
753 "uniform float FogRangeRecip;\n"
755 "uniform myhalf AmbientScale;\n"
756 "uniform myhalf DiffuseScale;\n"
757 "uniform myhalf SpecularScale;\n"
758 "uniform myhalf SpecularPower;\n"
760 "#ifdef USEOFFSETMAPPING\n"
761 "vec2 OffsetMapping(vec2 TexCoord)\n"
763 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
764 " // 14 sample relief mapping: linear search and then binary search\n"
765 " // this basically steps forward a small amount repeatedly until it finds\n"
766 " // itself inside solid, then jitters forward and back using decreasing\n"
767 " // amounts to find the impact\n"
768 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
769 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
770 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
771 " vec3 RT = vec3(TexCoord, 1);\n"
772 " OffsetVector *= 0.1;\n"
773 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
774 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
775 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
776 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
777 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
778 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
779 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
780 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
781 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
782 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
783 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
784 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
785 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
786 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
789 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
790 " // this basically moves forward the full distance, and then backs up based\n"
791 " // on height of samples\n"
792 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
793 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
794 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
795 " TexCoord += OffsetVector;\n"
796 " OffsetVector *= 0.333;\n"
797 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
798 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
799 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
800 " return TexCoord;\n"
803 "#endif // USEOFFSETMAPPING\n"
805 "#ifdef MODE_WATER\n"
810 "#ifdef USEOFFSETMAPPING\n"
811 " // apply offsetmapping\n"
812 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
813 "#define TexCoord TexCoordOffset\n"
816 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
817 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
818 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
819 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
820 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
823 "#else // !MODE_WATER\n"
824 "#ifdef MODE_REFRACTION\n"
826 "// refraction pass\n"
829 "#ifdef USEOFFSETMAPPING\n"
830 " // apply offsetmapping\n"
831 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
832 "#define TexCoord TexCoordOffset\n"
835 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
836 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
837 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
838 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
841 "#else // !MODE_REFRACTION\n"
844 "#ifdef USEOFFSETMAPPING\n"
845 " // apply offsetmapping\n"
846 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
847 "#define TexCoord TexCoordOffset\n"
850 " // combine the diffuse textures (base, pants, shirt)\n"
851 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
852 "#ifdef USECOLORMAPPING\n"
853 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
855 "#ifdef USEVERTEXTEXTUREBLEND\n"
856 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
857 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
858 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
859 " color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n"
860 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
863 "#ifdef USEDIFFUSE\n"
864 " // get the surface normal and the gloss color\n"
865 "# ifdef USEVERTEXTEXTUREBLEND\n"
866 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
867 "# ifdef USESPECULAR\n"
868 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
871 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
872 "# ifdef USESPECULAR\n"
873 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
880 "#ifdef MODE_LIGHTSOURCE\n"
883 " // calculate surface normal, light normal, and specular normal\n"
884 " // compute color intensity for the two textures (colormap and glossmap)\n"
885 " // scale by light color and attenuation as efficiently as possible\n"
886 " // (do as much scalar math as possible rather than vector math)\n"
887 "# ifdef USEDIFFUSE\n"
888 " // get the light normal\n"
889 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
891 "# ifdef USESPECULAR\n"
892 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
894 " // calculate directional shading\n"
895 " 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"
897 "# ifdef USEDIFFUSE\n"
898 " // calculate directional shading\n"
899 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
901 " // calculate directionless shading\n"
902 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
906 "# ifdef USECUBEFILTER\n"
907 " // apply light cubemap filter\n"
908 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
909 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
911 "#endif // MODE_LIGHTSOURCE\n"
916 "#ifdef MODE_LIGHTDIRECTION\n"
917 " // directional model lighting\n"
918 "# ifdef USEDIFFUSE\n"
919 " // get the light normal\n"
920 " myhalf3 diffusenormal = myhalf3(LightVector);\n"
922 "# ifdef USESPECULAR\n"
923 " // calculate directional shading\n"
924 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
925 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
926 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
928 "# ifdef USEDIFFUSE\n"
930 " // calculate directional shading\n"
931 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
933 " color.rgb *= AmbientColor;\n"
936 "#endif // MODE_LIGHTDIRECTION\n"
941 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
942 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
944 " // get the light normal\n"
945 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n"
946 " myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n"
947 " // calculate directional shading\n"
948 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
949 "# ifdef USESPECULAR\n"
950 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
951 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
954 " // apply lightmap color\n"
955 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
956 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
961 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
962 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
964 " // get the light normal\n"
965 " myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
966 " // calculate directional shading\n"
967 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
968 "# ifdef USESPECULAR\n"
969 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
970 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
973 " // apply lightmap color\n"
974 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
975 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
980 "#ifdef MODE_LIGHTMAP\n"
981 " // apply lightmap color\n"
982 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
983 "#endif // MODE_LIGHTMAP\n"
988 "#ifdef MODE_VERTEXCOLOR\n"
989 " // apply lightmap color\n"
990 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
991 "#endif // MODE_VERTEXCOLOR\n"
996 "#ifdef MODE_FLATCOLOR\n"
997 "#endif // MODE_FLATCOLOR\n"
1005 " color *= TintColor;\n"
1008 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1011 "#ifdef USECONTRASTBOOST\n"
1012 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1015 " color.rgb *= SceneBrightness;\n"
1017 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1019 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1022 " // 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"
1023 "#ifdef USEREFLECTION\n"
1024 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1025 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1026 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1027 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1030 " gl_FragColor = vec4(color);\n"
1032 "#endif // !MODE_REFRACTION\n"
1033 "#endif // !MODE_WATER\n"
1035 "#endif // FRAGMENT_SHADER\n"
1037 "#endif // !MODE_GENERIC\n"
1038 "#endif // !MODE_POSTPROCESS\n"
1039 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1042 typedef struct shaderpermutationinfo_s
1044 const char *pretext;
1047 shaderpermutationinfo_t;
1049 typedef struct shadermodeinfo_s
1051 const char *vertexfilename;
1052 const char *geometryfilename;
1053 const char *fragmentfilename;
1054 const char *pretext;
1059 typedef enum shaderpermutation_e
1061 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1062 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1063 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1064 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1065 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1066 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1067 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1068 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1069 SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1070 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface
1071 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1072 SHADERPERMUTATION_LIMIT = 1<<11, // size of permutations array
1073 SHADERPERMUTATION_COUNT = 11 // size of shaderpermutationinfo array
1075 shaderpermutation_t;
1077 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1078 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1080 {"#define USEDIFFUSE\n", " diffuse"},
1081 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1082 {"#define USECOLORMAPPING\n", " colormapping"},
1083 {"#define USECONTRASTBOOST\n", " contrastboost"},
1084 {"#define USEFOG\n", " fog"},
1085 {"#define USECUBEFILTER\n", " cubefilter"},
1086 {"#define USEGLOW\n", " glow"},
1087 {"#define USESPECULAR\n", " specular"},
1088 {"#define USEREFLECTION\n", " reflection"},
1089 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1090 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1093 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1094 typedef enum shadermode_e
1096 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1097 SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1098 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1099 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1100 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1101 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1102 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1103 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1104 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1105 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1106 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1107 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1112 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1113 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1115 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1116 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1117 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1118 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1119 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1120 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1121 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1122 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1123 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1124 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1125 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1126 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1129 typedef struct r_glsl_permutation_s
1131 // indicates if we have tried compiling this permutation already
1133 // 0 if compilation failed
1135 // locations of detected uniforms in program object, or -1 if not found
1136 int loc_Texture_First;
1137 int loc_Texture_Second;
1138 int loc_Texture_Normal;
1139 int loc_Texture_Color;
1140 int loc_Texture_Gloss;
1141 int loc_Texture_Glow;
1142 int loc_Texture_SecondaryNormal;
1143 int loc_Texture_SecondaryColor;
1144 int loc_Texture_SecondaryGloss;
1145 int loc_Texture_SecondaryGlow;
1146 int loc_Texture_Pants;
1147 int loc_Texture_Shirt;
1148 int loc_Texture_FogMask;
1149 int loc_Texture_Lightmap;
1150 int loc_Texture_Deluxemap;
1151 int loc_Texture_Attenuation;
1152 int loc_Texture_Cube;
1153 int loc_Texture_Refraction;
1154 int loc_Texture_Reflection;
1156 int loc_LightPosition;
1157 int loc_EyePosition;
1158 int loc_Color_Pants;
1159 int loc_Color_Shirt;
1160 int loc_FogRangeRecip;
1161 int loc_AmbientScale;
1162 int loc_DiffuseScale;
1163 int loc_SpecularScale;
1164 int loc_SpecularPower;
1166 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1167 int loc_OffsetMapping_Scale;
1169 int loc_AmbientColor;
1170 int loc_DiffuseColor;
1171 int loc_SpecularColor;
1173 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1174 int loc_DistortScaleRefractReflect;
1175 int loc_ScreenScaleRefractReflect;
1176 int loc_ScreenCenterRefractReflect;
1177 int loc_RefractColor;
1178 int loc_ReflectColor;
1179 int loc_ReflectFactor;
1180 int loc_ReflectOffset;
1182 r_glsl_permutation_t;
1184 // information about each possible shader permutation
1185 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1186 // currently selected permutation
1187 r_glsl_permutation_t *r_glsl_permutation;
1189 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1192 if (!filename || !filename[0])
1194 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1197 if (printfromdisknotice)
1198 Con_DPrint("from disk... ");
1199 return shaderstring;
1201 else if (!strcmp(filename, "glsl/default.glsl"))
1203 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1204 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1206 return shaderstring;
1209 static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t permutation)
1212 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1213 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1214 int vertstrings_count = 0;
1215 int geomstrings_count = 0;
1216 int fragstrings_count = 0;
1217 char *vertexstring, *geometrystring, *fragmentstring;
1218 const char *vertstrings_list[32+3];
1219 const char *geomstrings_list[32+3];
1220 const char *fragstrings_list[32+3];
1221 char permutationname[256];
1228 permutationname[0] = 0;
1229 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1230 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1231 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1233 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1235 // the first pretext is which type of shader to compile as
1236 // (later these will all be bound together as a program object)
1237 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1238 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1239 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1241 // the second pretext is the mode (for example a light source)
1242 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1243 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1244 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1245 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1247 // now add all the permutation pretexts
1248 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1250 if (permutation & (1<<i))
1252 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1253 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1254 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1255 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1259 // keep line numbers correct
1260 vertstrings_list[vertstrings_count++] = "\n";
1261 geomstrings_list[geomstrings_count++] = "\n";
1262 fragstrings_list[fragstrings_count++] = "\n";
1266 // now append the shader text itself
1267 vertstrings_list[vertstrings_count++] = vertexstring;
1268 geomstrings_list[geomstrings_count++] = geometrystring;
1269 fragstrings_list[fragstrings_count++] = fragmentstring;
1271 // if any sources were NULL, clear the respective list
1273 vertstrings_count = 0;
1274 if (!geometrystring)
1275 geomstrings_count = 0;
1276 if (!fragmentstring)
1277 fragstrings_count = 0;
1279 // compile the shader program
1280 if (vertstrings_count + geomstrings_count + fragstrings_count)
1281 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1285 qglUseProgramObjectARB(p->program);CHECKGLERROR
1286 // look up all the uniform variable names we care about, so we don't
1287 // have to look them up every time we set them
1288 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1289 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1290 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1291 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1292 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1293 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1294 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1295 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1296 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1297 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1298 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1299 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1300 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1301 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1302 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1303 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1304 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1305 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1306 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1307 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1308 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1309 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1310 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1311 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1312 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1313 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1314 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1315 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1316 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1317 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1318 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1319 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1320 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1321 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1322 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1323 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1324 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1325 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1326 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1327 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1328 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1329 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1330 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1331 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1332 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1333 // initialize the samplers to refer to the texture units we use
1334 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1335 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1336 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1337 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1338 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1339 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1340 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1341 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1342 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1343 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1344 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1345 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1346 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1347 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1348 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1349 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1350 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1351 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1352 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1354 if (developer.integer)
1355 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1358 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1362 Mem_Free(vertexstring);
1364 Mem_Free(geometrystring);
1366 Mem_Free(fragmentstring);
1369 void R_GLSL_Restart_f(void)
1372 shaderpermutation_t permutation;
1373 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1374 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1375 if (r_glsl_permutations[mode][permutation].program)
1376 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1377 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1380 void R_GLSL_DumpShader_f(void)
1384 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1387 Con_Printf("failed to write to glsl/default.glsl\n");
1391 FS_Print(file, "// The engine may define the following macros:\n");
1392 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1393 for (i = 0;i < SHADERMODE_COUNT;i++)
1394 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1395 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1396 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1397 FS_Print(file, "\n");
1398 FS_Print(file, builtinshaderstring);
1401 Con_Printf("glsl/default.glsl written\n");
1404 void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation)
1406 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1407 if (r_glsl_permutation != perm)
1409 r_glsl_permutation = perm;
1410 if (!r_glsl_permutation->program)
1412 if (!r_glsl_permutation->compiled)
1413 R_GLSL_CompilePermutation(mode, permutation);
1414 if (!r_glsl_permutation->program)
1416 // remove features until we find a valid permutation
1418 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1420 // reduce i more quickly whenever it would not remove any bits
1421 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1422 if (!(permutation & j))
1425 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1426 if (!r_glsl_permutation->compiled)
1427 R_GLSL_CompilePermutation(mode, permutation);
1428 if (r_glsl_permutation->program)
1431 if (i >= SHADERPERMUTATION_COUNT)
1433 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");
1434 Cvar_SetValueQuick(&r_glsl, 0);
1435 R_GLSL_Restart_f(); // unload shaders
1436 return; // no bit left to clear
1441 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1445 void R_SetupGenericShader(qboolean usetexture)
1447 if (gl_support_fragment_shader)
1449 if (r_glsl.integer && r_glsl_usegeneric.integer)
1450 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1451 else if (r_glsl_permutation)
1453 r_glsl_permutation = NULL;
1454 qglUseProgramObjectARB(0);CHECKGLERROR
1459 void R_SetupGenericTwoTextureShader(int texturemode)
1461 if (gl_support_fragment_shader)
1463 if (r_glsl.integer && r_glsl_usegeneric.integer)
1464 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1465 else if (r_glsl_permutation)
1467 r_glsl_permutation = NULL;
1468 qglUseProgramObjectARB(0);CHECKGLERROR
1471 if (!r_glsl_permutation)
1473 if (texturemode == GL_DECAL && gl_combine.integer)
1474 texturemode = GL_INTERPOLATE_ARB;
1475 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1479 void R_SetupDepthOrShadowShader(void)
1481 if (gl_support_fragment_shader)
1483 if (r_glsl.integer && r_glsl_usegeneric.integer)
1484 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1485 else if (r_glsl_permutation)
1487 r_glsl_permutation = NULL;
1488 qglUseProgramObjectARB(0);CHECKGLERROR
1493 extern rtexture_t *r_shadow_attenuationgradienttexture;
1494 extern rtexture_t *r_shadow_attenuation2dtexture;
1495 extern rtexture_t *r_shadow_attenuation3dtexture;
1496 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1498 // select a permutation of the lighting shader appropriate to this
1499 // combination of texture, entity, light source, and fogging, only use the
1500 // minimum features necessary to avoid wasting rendering time in the
1501 // fragment shader on features that are not being used
1502 unsigned int permutation = 0;
1503 shadermode_t mode = 0;
1504 // TODO: implement geometry-shader based shadow volumes someday
1505 if (r_glsl_offsetmapping.integer)
1507 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1508 if (r_glsl_offsetmapping_reliefmapping.integer)
1509 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1511 if (rsurfacepass == RSURFPASS_BACKGROUND)
1513 // distorted background
1514 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1515 mode = SHADERMODE_WATER;
1517 mode = SHADERMODE_REFRACTION;
1519 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1522 mode = SHADERMODE_LIGHTSOURCE;
1523 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1524 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1525 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1526 permutation |= SHADERPERMUTATION_CUBEFILTER;
1527 if (diffusescale > 0)
1528 permutation |= SHADERPERMUTATION_DIFFUSE;
1529 if (specularscale > 0)
1530 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1531 if (r_refdef.fogenabled)
1532 permutation |= SHADERPERMUTATION_FOG;
1533 if (rsurface.texture->colormapping)
1534 permutation |= SHADERPERMUTATION_COLORMAPPING;
1535 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1536 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1538 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1540 // unshaded geometry (fullbright or ambient model lighting)
1541 mode = SHADERMODE_FLATCOLOR;
1542 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1543 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1544 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1545 permutation |= SHADERPERMUTATION_GLOW;
1546 if (r_refdef.fogenabled)
1547 permutation |= SHADERPERMUTATION_FOG;
1548 if (rsurface.texture->colormapping)
1549 permutation |= SHADERPERMUTATION_COLORMAPPING;
1550 if (r_glsl_offsetmapping.integer)
1552 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1553 if (r_glsl_offsetmapping_reliefmapping.integer)
1554 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1556 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1557 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1558 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1559 permutation |= SHADERPERMUTATION_REFLECTION;
1561 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1563 // directional model lighting
1564 mode = SHADERMODE_LIGHTDIRECTION;
1565 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1566 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1567 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1568 permutation |= SHADERPERMUTATION_GLOW;
1569 permutation |= SHADERPERMUTATION_DIFFUSE;
1570 if (specularscale > 0)
1571 permutation |= SHADERPERMUTATION_SPECULAR;
1572 if (r_refdef.fogenabled)
1573 permutation |= SHADERPERMUTATION_FOG;
1574 if (rsurface.texture->colormapping)
1575 permutation |= SHADERPERMUTATION_COLORMAPPING;
1576 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1577 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1578 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1579 permutation |= SHADERPERMUTATION_REFLECTION;
1581 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1583 // ambient model lighting
1584 mode = SHADERMODE_LIGHTDIRECTION;
1585 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1586 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1587 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1588 permutation |= SHADERPERMUTATION_GLOW;
1589 if (r_refdef.fogenabled)
1590 permutation |= SHADERPERMUTATION_FOG;
1591 if (rsurface.texture->colormapping)
1592 permutation |= SHADERPERMUTATION_COLORMAPPING;
1593 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1594 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1595 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1596 permutation |= SHADERPERMUTATION_REFLECTION;
1601 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1603 // deluxemapping (light direction texture)
1604 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1605 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1607 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1608 permutation |= SHADERPERMUTATION_DIFFUSE;
1609 if (specularscale > 0)
1610 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1612 else if (r_glsl_deluxemapping.integer >= 2)
1614 // fake deluxemapping (uniform light direction in tangentspace)
1615 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1616 permutation |= SHADERPERMUTATION_DIFFUSE;
1617 if (specularscale > 0)
1618 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1620 else if (rsurface.uselightmaptexture)
1622 // ordinary lightmapping (q1bsp, q3bsp)
1623 mode = SHADERMODE_LIGHTMAP;
1627 // ordinary vertex coloring (q3bsp)
1628 mode = SHADERMODE_VERTEXCOLOR;
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;
1643 R_SetupShader_SetPermutation(mode, permutation);
1644 if (mode == SHADERMODE_LIGHTSOURCE)
1646 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1647 if (permutation & SHADERPERMUTATION_DIFFUSE)
1649 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1650 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1651 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1652 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1656 // ambient only is simpler
1657 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]);
1658 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1659 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1660 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1662 // additive passes are only darkened by fog, not tinted
1663 if (r_glsl_permutation->loc_FogColor >= 0)
1664 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1668 if (mode == SHADERMODE_LIGHTDIRECTION)
1670 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);
1671 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);
1672 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);
1673 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]);
1677 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1678 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1679 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1681 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]);
1682 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1683 // additive passes are only darkened by fog, not tinted
1684 if (r_glsl_permutation->loc_FogColor >= 0)
1686 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1687 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1689 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1691 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);
1692 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]);
1693 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]);
1694 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1695 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1696 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1697 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1699 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1701 // The formula used is actually:
1702 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1703 // color.rgb *= SceneBrightness;
1705 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1706 // and do [[calculations]] here in the engine
1707 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1708 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1711 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1712 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1713 if (r_glsl_permutation->loc_Color_Pants >= 0)
1715 if (rsurface.texture->currentskinframe->pants)
1716 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1718 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1720 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1722 if (rsurface.texture->currentskinframe->shirt)
1723 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1725 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1727 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1728 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1729 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1733 #define SKINFRAME_HASH 1024
1737 int loadsequence; // incremented each level change
1738 memexpandablearray_t array;
1739 skinframe_t *hash[SKINFRAME_HASH];
1743 void R_SkinFrame_PrepareForPurge(void)
1745 r_skinframe.loadsequence++;
1746 // wrap it without hitting zero
1747 if (r_skinframe.loadsequence >= 200)
1748 r_skinframe.loadsequence = 1;
1751 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1755 // mark the skinframe as used for the purging code
1756 skinframe->loadsequence = r_skinframe.loadsequence;
1759 void R_SkinFrame_Purge(void)
1763 for (i = 0;i < SKINFRAME_HASH;i++)
1765 for (s = r_skinframe.hash[i];s;s = s->next)
1767 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1769 if (s->merged == s->base)
1771 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1772 R_PurgeTexture(s->stain );s->stain = NULL;
1773 R_PurgeTexture(s->merged);s->merged = NULL;
1774 R_PurgeTexture(s->base );s->base = NULL;
1775 R_PurgeTexture(s->pants );s->pants = NULL;
1776 R_PurgeTexture(s->shirt );s->shirt = NULL;
1777 R_PurgeTexture(s->nmap );s->nmap = NULL;
1778 R_PurgeTexture(s->gloss );s->gloss = NULL;
1779 R_PurgeTexture(s->glow );s->glow = NULL;
1780 R_PurgeTexture(s->fog );s->fog = NULL;
1781 s->loadsequence = 0;
1787 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1789 char basename[MAX_QPATH];
1791 Image_StripImageExtension(name, basename, sizeof(basename));
1793 if( last == NULL ) {
1795 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1796 item = r_skinframe.hash[hashindex];
1801 // linearly search through the hash bucket
1802 for( ; item ; item = item->next ) {
1803 if( !strcmp( item->basename, basename ) ) {
1810 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1814 char basename[MAX_QPATH];
1816 Image_StripImageExtension(name, basename, sizeof(basename));
1818 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1819 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1820 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1824 rtexture_t *dyntexture;
1825 // check whether its a dynamic texture
1826 dyntexture = CL_GetDynTexture( basename );
1827 if (!add && !dyntexture)
1829 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1830 memset(item, 0, sizeof(*item));
1831 strlcpy(item->basename, basename, sizeof(item->basename));
1832 item->base = dyntexture; // either NULL or dyntexture handle
1833 item->textureflags = textureflags;
1834 item->comparewidth = comparewidth;
1835 item->compareheight = compareheight;
1836 item->comparecrc = comparecrc;
1837 item->next = r_skinframe.hash[hashindex];
1838 r_skinframe.hash[hashindex] = item;
1840 else if( item->base == NULL )
1842 rtexture_t *dyntexture;
1843 // check whether its a dynamic texture
1844 // 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]
1845 dyntexture = CL_GetDynTexture( basename );
1846 item->base = dyntexture; // either NULL or dyntexture handle
1849 R_SkinFrame_MarkUsed(item);
1853 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1855 // FIXME: it should be possible to disable loading various layers using
1856 // cvars, to prevent wasted loading time and memory usage if the user does
1858 qboolean loadnormalmap = true;
1859 qboolean loadgloss = true;
1860 qboolean loadpantsandshirt = true;
1861 qboolean loadglow = true;
1863 unsigned char *pixels;
1864 unsigned char *bumppixels;
1865 unsigned char *basepixels = NULL;
1866 int basepixels_width;
1867 int basepixels_height;
1868 skinframe_t *skinframe;
1870 if (cls.state == ca_dedicated)
1873 // return an existing skinframe if already loaded
1874 // if loading of the first image fails, don't make a new skinframe as it
1875 // would cause all future lookups of this to be missing
1876 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1877 if (skinframe && skinframe->base)
1880 basepixels = loadimagepixelsbgra(name, complain, true);
1881 if (basepixels == NULL)
1884 // we've got some pixels to store, so really allocate this new texture now
1886 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1887 skinframe->stain = NULL;
1888 skinframe->merged = NULL;
1889 skinframe->base = r_texture_notexture;
1890 skinframe->pants = NULL;
1891 skinframe->shirt = NULL;
1892 skinframe->nmap = r_texture_blanknormalmap;
1893 skinframe->gloss = NULL;
1894 skinframe->glow = NULL;
1895 skinframe->fog = NULL;
1897 basepixels_width = image_width;
1898 basepixels_height = image_height;
1899 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);
1901 if (textureflags & TEXF_ALPHA)
1903 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1904 if (basepixels[j] < 255)
1906 if (j < basepixels_width * basepixels_height * 4)
1908 // has transparent pixels
1909 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1910 for (j = 0;j < image_width * image_height * 4;j += 4)
1915 pixels[j+3] = basepixels[j+3];
1917 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);
1922 // _norm is the name used by tenebrae and has been adopted as standard
1925 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1927 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1931 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1933 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1934 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1935 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1937 Mem_Free(bumppixels);
1939 else if (r_shadow_bumpscale_basetexture.value > 0)
1941 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1942 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1943 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1947 // _luma is supported for tenebrae compatibility
1948 // (I think it's a very stupid name, but oh well)
1949 // _glow is the preferred name
1950 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;}
1951 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;}
1952 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;}
1953 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;}
1956 Mem_Free(basepixels);
1961 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)
1966 for (i = 0;i < width*height;i++)
1967 if (((unsigned char *)&palette[in[i]])[3] > 0)
1969 if (i == width*height)
1972 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1975 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1976 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1979 unsigned char *temp1, *temp2;
1980 skinframe_t *skinframe;
1982 if (cls.state == ca_dedicated)
1985 // if already loaded just return it, otherwise make a new skinframe
1986 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1987 if (skinframe && skinframe->base)
1990 skinframe->stain = NULL;
1991 skinframe->merged = NULL;
1992 skinframe->base = r_texture_notexture;
1993 skinframe->pants = NULL;
1994 skinframe->shirt = NULL;
1995 skinframe->nmap = r_texture_blanknormalmap;
1996 skinframe->gloss = NULL;
1997 skinframe->glow = NULL;
1998 skinframe->fog = NULL;
2000 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2004 if (r_shadow_bumpscale_basetexture.value > 0)
2006 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2007 temp2 = temp1 + width * height * 4;
2008 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2009 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2012 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2013 if (textureflags & TEXF_ALPHA)
2015 for (i = 3;i < width * height * 4;i += 4)
2016 if (skindata[i] < 255)
2018 if (i < width * height * 4)
2020 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2021 memcpy(fogpixels, skindata, width * height * 4);
2022 for (i = 0;i < width * height * 4;i += 4)
2023 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2024 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2025 Mem_Free(fogpixels);
2032 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2035 unsigned char *temp1, *temp2;
2036 skinframe_t *skinframe;
2038 if (cls.state == ca_dedicated)
2041 // if already loaded just return it, otherwise make a new skinframe
2042 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2043 if (skinframe && skinframe->base)
2046 skinframe->stain = NULL;
2047 skinframe->merged = NULL;
2048 skinframe->base = r_texture_notexture;
2049 skinframe->pants = NULL;
2050 skinframe->shirt = NULL;
2051 skinframe->nmap = r_texture_blanknormalmap;
2052 skinframe->gloss = NULL;
2053 skinframe->glow = NULL;
2054 skinframe->fog = NULL;
2056 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2060 if (r_shadow_bumpscale_basetexture.value > 0)
2062 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2063 temp2 = temp1 + width * height * 4;
2064 // use either a custom palette or the quake palette
2065 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2066 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2067 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2070 // use either a custom palette, or the quake palette
2071 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
2072 if (loadglowtexture)
2073 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2074 if (loadpantsandshirt)
2076 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2077 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2079 if (skinframe->pants || skinframe->shirt)
2080 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
2081 if (textureflags & TEXF_ALPHA)
2083 for (i = 0;i < width * height;i++)
2084 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2086 if (i < width * height)
2087 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2093 skinframe_t *R_SkinFrame_LoadMissing(void)
2095 skinframe_t *skinframe;
2097 if (cls.state == ca_dedicated)
2100 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2101 skinframe->stain = NULL;
2102 skinframe->merged = NULL;
2103 skinframe->base = r_texture_notexture;
2104 skinframe->pants = NULL;
2105 skinframe->shirt = NULL;
2106 skinframe->nmap = r_texture_blanknormalmap;
2107 skinframe->gloss = NULL;
2108 skinframe->glow = NULL;
2109 skinframe->fog = NULL;
2114 void gl_main_start(void)
2116 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2117 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2119 // set up r_skinframe loading system for textures
2120 memset(&r_skinframe, 0, sizeof(r_skinframe));
2121 r_skinframe.loadsequence = 1;
2122 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2124 r_main_texturepool = R_AllocTexturePool();
2125 R_BuildBlankTextures();
2127 if (gl_texturecubemap)
2130 R_BuildNormalizationCube();
2132 r_texture_fogattenuation = NULL;
2133 //r_texture_fogintensity = NULL;
2134 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2135 memset(&r_waterstate, 0, sizeof(r_waterstate));
2136 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2137 memset(&r_svbsp, 0, sizeof (r_svbsp));
2139 r_refdef.fogmasktable_density = 0;
2142 void gl_main_shutdown(void)
2144 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2145 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2147 // clear out the r_skinframe state
2148 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2149 memset(&r_skinframe, 0, sizeof(r_skinframe));
2152 Mem_Free(r_svbsp.nodes);
2153 memset(&r_svbsp, 0, sizeof (r_svbsp));
2154 R_FreeTexturePool(&r_main_texturepool);
2155 r_texture_blanknormalmap = NULL;
2156 r_texture_white = NULL;
2157 r_texture_grey128 = NULL;
2158 r_texture_black = NULL;
2159 r_texture_whitecube = NULL;
2160 r_texture_normalizationcube = NULL;
2161 r_texture_fogattenuation = NULL;
2162 //r_texture_fogintensity = NULL;
2163 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2164 memset(&r_waterstate, 0, sizeof(r_waterstate));
2168 extern void CL_ParseEntityLump(char *entitystring);
2169 void gl_main_newmap(void)
2171 // FIXME: move this code to client
2173 char *entities, entname[MAX_QPATH];
2176 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2177 l = (int)strlen(entname) - 4;
2178 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2180 memcpy(entname + l, ".ent", 5);
2181 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2183 CL_ParseEntityLump(entities);
2188 if (cl.worldmodel->brush.entities)
2189 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2193 void GL_Main_Init(void)
2195 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2197 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2198 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2199 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2200 if (gamemode == GAME_NEHAHRA)
2202 Cvar_RegisterVariable (&gl_fogenable);
2203 Cvar_RegisterVariable (&gl_fogdensity);
2204 Cvar_RegisterVariable (&gl_fogred);
2205 Cvar_RegisterVariable (&gl_foggreen);
2206 Cvar_RegisterVariable (&gl_fogblue);
2207 Cvar_RegisterVariable (&gl_fogstart);
2208 Cvar_RegisterVariable (&gl_fogend);
2209 Cvar_RegisterVariable (&gl_skyclip);
2211 Cvar_RegisterVariable(&r_depthfirst);
2212 Cvar_RegisterVariable(&r_nearclip);
2213 Cvar_RegisterVariable(&r_showbboxes);
2214 Cvar_RegisterVariable(&r_showsurfaces);
2215 Cvar_RegisterVariable(&r_showtris);
2216 Cvar_RegisterVariable(&r_shownormals);
2217 Cvar_RegisterVariable(&r_showlighting);
2218 Cvar_RegisterVariable(&r_showshadowvolumes);
2219 Cvar_RegisterVariable(&r_showcollisionbrushes);
2220 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2221 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2222 Cvar_RegisterVariable(&r_showdisabledepthtest);
2223 Cvar_RegisterVariable(&r_drawportals);
2224 Cvar_RegisterVariable(&r_drawentities);
2225 Cvar_RegisterVariable(&r_cullentities_trace);
2226 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2227 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2228 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2229 Cvar_RegisterVariable(&r_drawviewmodel);
2230 Cvar_RegisterVariable(&r_speeds);
2231 Cvar_RegisterVariable(&r_fullbrights);
2232 Cvar_RegisterVariable(&r_wateralpha);
2233 Cvar_RegisterVariable(&r_dynamic);
2234 Cvar_RegisterVariable(&r_fullbright);
2235 Cvar_RegisterVariable(&r_shadows);
2236 Cvar_RegisterVariable(&r_shadows_throwdistance);
2237 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2238 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2239 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2240 Cvar_RegisterVariable(&r_fog_exp2);
2241 Cvar_RegisterVariable(&r_textureunits);
2242 Cvar_RegisterVariable(&r_glsl);
2243 Cvar_RegisterVariable(&r_glsl_contrastboost);
2244 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2245 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2246 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2247 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2248 Cvar_RegisterVariable(&r_glsl_postprocess);
2249 Cvar_RegisterVariable(&r_glsl_postprocess_contrastboost);
2250 Cvar_RegisterVariable(&r_glsl_usegeneric);
2251 Cvar_RegisterVariable(&r_water);
2252 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2253 Cvar_RegisterVariable(&r_water_clippingplanebias);
2254 Cvar_RegisterVariable(&r_water_refractdistort);
2255 Cvar_RegisterVariable(&r_water_reflectdistort);
2256 Cvar_RegisterVariable(&r_lerpsprites);
2257 Cvar_RegisterVariable(&r_lerpmodels);
2258 Cvar_RegisterVariable(&r_lerplightstyles);
2259 Cvar_RegisterVariable(&r_waterscroll);
2260 Cvar_RegisterVariable(&r_bloom);
2261 Cvar_RegisterVariable(&r_bloom_colorscale);
2262 Cvar_RegisterVariable(&r_bloom_brighten);
2263 Cvar_RegisterVariable(&r_bloom_blur);
2264 Cvar_RegisterVariable(&r_bloom_resolution);
2265 Cvar_RegisterVariable(&r_bloom_colorexponent);
2266 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2267 Cvar_RegisterVariable(&r_hdr);
2268 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2269 Cvar_RegisterVariable(&r_hdr_glowintensity);
2270 Cvar_RegisterVariable(&r_hdr_range);
2271 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2272 Cvar_RegisterVariable(&developer_texturelogging);
2273 Cvar_RegisterVariable(&gl_lightmaps);
2274 Cvar_RegisterVariable(&r_test);
2275 Cvar_RegisterVariable(&r_batchmode);
2276 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2277 Cvar_SetValue("r_fullbrights", 0);
2278 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2280 Cvar_RegisterVariable(&r_track_sprites);
2281 Cvar_RegisterVariable(&r_track_sprites_flags);
2282 Cvar_RegisterVariable(&r_track_sprites_scalew);
2283 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2286 extern void R_Textures_Init(void);
2287 extern void GL_Draw_Init(void);
2288 extern void GL_Main_Init(void);
2289 extern void R_Shadow_Init(void);
2290 extern void R_Sky_Init(void);
2291 extern void GL_Surf_Init(void);
2292 extern void R_Particles_Init(void);
2293 extern void R_Explosion_Init(void);
2294 extern void gl_backend_init(void);
2295 extern void Sbar_Init(void);
2296 extern void R_LightningBeams_Init(void);
2297 extern void Mod_RenderInit(void);
2299 void Render_Init(void)
2311 R_LightningBeams_Init();
2320 extern char *ENGINE_EXTENSIONS;
2323 VID_CheckExtensions();
2325 // LordHavoc: report supported extensions
2326 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2328 // clear to black (loading plaque will be seen over this)
2330 qglClearColor(0,0,0,1);CHECKGLERROR
2331 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2334 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2338 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2340 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2343 p = r_refdef.view.frustum + i;
2348 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2352 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2356 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2360 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2364 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2368 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2372 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2376 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2384 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2388 for (i = 0;i < numplanes;i++)
2395 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2399 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2403 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2407 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2411 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2415 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2419 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2423 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2431 //==================================================================================
2433 static void R_View_UpdateEntityVisible (void)
2436 entity_render_t *ent;
2438 if (!r_drawentities.integer)
2441 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2442 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2444 // worldmodel can check visibility
2445 for (i = 0;i < r_refdef.scene.numentities;i++)
2447 ent = r_refdef.scene.entities[i];
2448 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)) && ((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));
2451 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2453 for (i = 0;i < r_refdef.scene.numentities;i++)
2455 ent = r_refdef.scene.entities[i];
2456 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2458 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))
2459 ent->last_trace_visibility = realtime;
2460 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2461 r_refdef.viewcache.entityvisible[i] = 0;
2468 // no worldmodel or it can't check visibility
2469 for (i = 0;i < r_refdef.scene.numentities;i++)
2471 ent = r_refdef.scene.entities[i];
2472 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));
2477 // only used if skyrendermasked, and normally returns false
2478 int R_DrawBrushModelsSky (void)
2481 entity_render_t *ent;
2483 if (!r_drawentities.integer)
2487 for (i = 0;i < r_refdef.scene.numentities;i++)
2489 if (!r_refdef.viewcache.entityvisible[i])
2491 ent = r_refdef.scene.entities[i];
2492 if (!ent->model || !ent->model->DrawSky)
2494 ent->model->DrawSky(ent);
2500 static void R_DrawNoModel(entity_render_t *ent);
2501 static void R_DrawModels(void)
2504 entity_render_t *ent;
2506 if (!r_drawentities.integer)
2509 for (i = 0;i < r_refdef.scene.numentities;i++)
2511 if (!r_refdef.viewcache.entityvisible[i])
2513 ent = r_refdef.scene.entities[i];
2514 r_refdef.stats.entities++;
2515 if (ent->model && ent->model->Draw != NULL)
2516 ent->model->Draw(ent);
2522 static void R_DrawModelsDepth(void)
2525 entity_render_t *ent;
2527 if (!r_drawentities.integer)
2530 for (i = 0;i < r_refdef.scene.numentities;i++)
2532 if (!r_refdef.viewcache.entityvisible[i])
2534 ent = r_refdef.scene.entities[i];
2535 if (ent->model && ent->model->DrawDepth != NULL)
2536 ent->model->DrawDepth(ent);
2540 static void R_DrawModelsDebug(void)
2543 entity_render_t *ent;
2545 if (!r_drawentities.integer)
2548 for (i = 0;i < r_refdef.scene.numentities;i++)
2550 if (!r_refdef.viewcache.entityvisible[i])
2552 ent = r_refdef.scene.entities[i];
2553 if (ent->model && ent->model->DrawDebug != NULL)
2554 ent->model->DrawDebug(ent);
2558 static void R_DrawModelsAddWaterPlanes(void)
2561 entity_render_t *ent;
2563 if (!r_drawentities.integer)
2566 for (i = 0;i < r_refdef.scene.numentities;i++)
2568 if (!r_refdef.viewcache.entityvisible[i])
2570 ent = r_refdef.scene.entities[i];
2571 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2572 ent->model->DrawAddWaterPlanes(ent);
2576 static void R_View_SetFrustum(void)
2579 double slopex, slopey;
2580 vec3_t forward, left, up, origin;
2582 // we can't trust r_refdef.view.forward and friends in reflected scenes
2583 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2586 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2587 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2588 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2589 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2590 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2591 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2592 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2593 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2594 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2595 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2596 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2597 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2601 zNear = r_refdef.nearclip;
2602 nudge = 1.0 - 1.0 / (1<<23);
2603 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2604 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2605 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2606 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2607 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2608 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2609 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2610 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2616 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2617 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2618 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2619 r_refdef.view.frustum[0].dist = m[15] - m[12];
2621 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2622 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2623 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2624 r_refdef.view.frustum[1].dist = m[15] + m[12];
2626 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2627 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2628 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2629 r_refdef.view.frustum[2].dist = m[15] - m[13];
2631 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2632 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2633 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2634 r_refdef.view.frustum[3].dist = m[15] + m[13];
2636 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2637 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2638 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2639 r_refdef.view.frustum[4].dist = m[15] - m[14];
2641 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2642 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2643 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2644 r_refdef.view.frustum[5].dist = m[15] + m[14];
2647 if (r_refdef.view.useperspective)
2649 slopex = 1.0 / r_refdef.view.frustum_x;
2650 slopey = 1.0 / r_refdef.view.frustum_y;
2651 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2652 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2653 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2654 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2655 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2657 // Leaving those out was a mistake, those were in the old code, and they
2658 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2659 // I couldn't reproduce it after adding those normalizations. --blub
2660 VectorNormalize(r_refdef.view.frustum[0].normal);
2661 VectorNormalize(r_refdef.view.frustum[1].normal);
2662 VectorNormalize(r_refdef.view.frustum[2].normal);
2663 VectorNormalize(r_refdef.view.frustum[3].normal);
2665 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2666 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2667 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2668 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2669 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2671 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2672 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2673 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2674 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2675 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2679 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2680 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2681 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2682 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2683 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2684 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2685 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2686 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2687 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2688 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2690 r_refdef.view.numfrustumplanes = 5;
2692 if (r_refdef.view.useclipplane)
2694 r_refdef.view.numfrustumplanes = 6;
2695 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2698 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2699 PlaneClassify(r_refdef.view.frustum + i);
2701 // LordHavoc: note to all quake engine coders, Quake had a special case
2702 // for 90 degrees which assumed a square view (wrong), so I removed it,
2703 // Quake2 has it disabled as well.
2705 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2706 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2707 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2708 //PlaneClassify(&frustum[0]);
2710 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2711 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2712 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2713 //PlaneClassify(&frustum[1]);
2715 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2716 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2717 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2718 //PlaneClassify(&frustum[2]);
2720 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2721 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2722 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2723 //PlaneClassify(&frustum[3]);
2726 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2727 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2728 //PlaneClassify(&frustum[4]);
2731 void R_View_Update(void)
2733 R_View_SetFrustum();
2734 R_View_WorldVisibility(r_refdef.view.useclipplane);
2735 R_View_UpdateEntityVisible();
2738 void R_SetupView(qboolean allowwaterclippingplane)
2740 if (!r_refdef.view.useperspective)
2741 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);
2742 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2743 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2745 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2747 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2749 if (r_refdef.view.useclipplane && allowwaterclippingplane)
2751 // LordHavoc: couldn't figure out how to make this approach the
2752 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2753 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2754 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2755 dist = r_refdef.view.clipplane.dist;
2756 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2760 void R_ResetViewRendering2D(void)
2764 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2765 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2766 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2767 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2768 GL_Color(1, 1, 1, 1);
2769 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2770 GL_BlendFunc(GL_ONE, GL_ZERO);
2771 GL_AlphaTest(false);
2772 GL_ScissorTest(false);
2773 GL_DepthMask(false);
2774 GL_DepthRange(0, 1);
2775 GL_DepthTest(false);
2776 R_Mesh_Matrix(&identitymatrix);
2777 R_Mesh_ResetTextureState();
2778 GL_PolygonOffset(0, 0);
2779 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2780 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2781 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2782 qglStencilMask(~0);CHECKGLERROR
2783 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2784 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2785 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2786 R_SetupGenericShader(true);
2789 void R_ResetViewRendering3D(void)
2793 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2794 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2796 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2797 GL_Color(1, 1, 1, 1);
2798 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2799 GL_BlendFunc(GL_ONE, GL_ZERO);
2800 GL_AlphaTest(false);
2801 GL_ScissorTest(true);
2803 GL_DepthRange(0, 1);
2805 R_Mesh_Matrix(&identitymatrix);
2806 R_Mesh_ResetTextureState();
2807 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2808 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2809 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2810 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2811 qglStencilMask(~0);CHECKGLERROR
2812 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2813 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2814 GL_CullFace(r_refdef.view.cullface_back);
2815 R_SetupGenericShader(true);
2818 void R_RenderScene(qboolean addwaterplanes);
2820 static void R_Water_StartFrame(void)
2823 int waterwidth, waterheight, texturewidth, textureheight;
2824 r_waterstate_waterplane_t *p;
2826 // set waterwidth and waterheight to the water resolution that will be
2827 // used (often less than the screen resolution for faster rendering)
2828 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2829 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2831 // calculate desired texture sizes
2832 // can't use water if the card does not support the texture size
2833 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2834 texturewidth = textureheight = waterwidth = waterheight = 0;
2835 else if (gl_support_arb_texture_non_power_of_two)
2837 texturewidth = waterwidth;
2838 textureheight = waterheight;
2842 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2843 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2846 // allocate textures as needed
2847 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2849 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2850 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2852 if (p->texture_refraction)
2853 R_FreeTexture(p->texture_refraction);
2854 p->texture_refraction = NULL;
2855 if (p->texture_reflection)
2856 R_FreeTexture(p->texture_reflection);
2857 p->texture_reflection = NULL;
2859 memset(&r_waterstate, 0, sizeof(r_waterstate));
2860 r_waterstate.waterwidth = waterwidth;
2861 r_waterstate.waterheight = waterheight;
2862 r_waterstate.texturewidth = texturewidth;
2863 r_waterstate.textureheight = textureheight;
2866 if (r_waterstate.waterwidth)
2868 r_waterstate.enabled = true;
2870 // set up variables that will be used in shader setup
2871 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2872 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2873 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2874 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2877 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2878 r_waterstate.numwaterplanes = 0;
2881 static void R_Water_AddWaterPlane(msurface_t *surface)
2883 int triangleindex, planeindex;
2888 r_waterstate_waterplane_t *p;
2889 // just use the first triangle with a valid normal for any decisions
2890 VectorClear(normal);
2891 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2893 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2894 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2895 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2896 TriangleNormal(vert[0], vert[1], vert[2], normal);
2897 if (VectorLength2(normal) >= 0.001)
2901 // find a matching plane if there is one
2902 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2903 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2905 if (planeindex >= r_waterstate.maxwaterplanes)
2906 return; // nothing we can do, out of planes
2908 // if this triangle does not fit any known plane rendered this frame, add one
2909 if (planeindex >= r_waterstate.numwaterplanes)
2911 // store the new plane
2912 r_waterstate.numwaterplanes++;
2913 VectorCopy(normal, p->plane.normal);
2914 VectorNormalize(p->plane.normal);
2915 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2916 PlaneClassify(&p->plane);
2917 // flip the plane if it does not face the viewer
2918 if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0)
2920 VectorNegate(p->plane.normal, p->plane.normal);
2921 p->plane.dist *= -1;
2922 PlaneClassify(&p->plane);
2924 // clear materialflags and pvs
2925 p->materialflags = 0;
2926 p->pvsvalid = false;
2928 // merge this surface's materialflags into the waterplane
2929 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2930 // merge this surface's PVS into the waterplane
2931 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2932 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
2933 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
2935 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2940 static void R_Water_ProcessPlanes(void)
2942 r_refdef_view_t originalview;
2944 r_waterstate_waterplane_t *p;
2946 originalview = r_refdef.view;
2948 // make sure enough textures are allocated
2949 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2951 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2953 if (!p->texture_refraction)
2954 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);
2955 if (!p->texture_refraction)
2959 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2961 if (!p->texture_reflection)
2962 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);
2963 if (!p->texture_reflection)
2969 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2971 r_refdef.view.showdebug = false;
2972 r_refdef.view.width = r_waterstate.waterwidth;
2973 r_refdef.view.height = r_waterstate.waterheight;
2974 r_refdef.view.useclipplane = true;
2975 r_waterstate.renderingscene = true;
2977 // render the normal view scene and copy into texture
2978 // (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)
2979 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2981 r_refdef.view.clipplane = p->plane;
2982 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
2983 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
2984 PlaneClassify(&r_refdef.view.clipplane);
2986 R_RenderScene(false);
2988 // copy view into the screen texture
2989 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2990 GL_ActiveTexture(0);
2992 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
2995 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2997 // render reflected scene and copy into texture
2998 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2999 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3000 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3001 r_refdef.view.clipplane = p->plane;
3002 // reverse the cullface settings for this render
3003 r_refdef.view.cullface_front = GL_FRONT;
3004 r_refdef.view.cullface_back = GL_BACK;
3005 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3007 r_refdef.view.usecustompvs = true;
3009 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3011 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3014 R_ResetViewRendering3D();
3015 R_ClearScreen(r_refdef.fogenabled);
3016 if (r_timereport_active)
3017 R_TimeReport("viewclear");
3019 R_RenderScene(false);
3021 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3022 GL_ActiveTexture(0);
3024 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
3026 R_ResetViewRendering3D();
3027 R_ClearScreen(r_refdef.fogenabled);
3028 if (r_timereport_active)
3029 R_TimeReport("viewclear");
3032 r_refdef.view = originalview;
3033 r_refdef.view.clear = true;
3034 r_waterstate.renderingscene = false;
3038 r_refdef.view = originalview;
3039 r_waterstate.renderingscene = false;
3040 Cvar_SetValueQuick(&r_water, 0);
3041 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3045 void R_Bloom_StartFrame(void)
3047 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3049 // set bloomwidth and bloomheight to the bloom resolution that will be
3050 // used (often less than the screen resolution for faster rendering)
3051 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3052 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3053 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3054 r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3055 r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3057 // calculate desired texture sizes
3058 if (gl_support_arb_texture_non_power_of_two)
3060 screentexturewidth = r_refdef.view.width;
3061 screentextureheight = r_refdef.view.height;
3062 bloomtexturewidth = r_bloomstate.bloomwidth;
3063 bloomtextureheight = r_bloomstate.bloomheight;
3067 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3068 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3069 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3070 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3073 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))
3075 Cvar_SetValueQuick(&r_hdr, 0);
3076 Cvar_SetValueQuick(&r_bloom, 0);
3079 if (!(r_glsl.integer && (r_glsl_postprocess.integer || r_bloom.integer || r_hdr.integer)) && !r_bloom.integer)
3080 screentexturewidth = screentextureheight = 0;
3081 if (!r_hdr.integer && !r_bloom.integer)
3082 bloomtexturewidth = bloomtextureheight = 0;
3084 // allocate textures as needed
3085 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3087 if (r_bloomstate.texture_screen)
3088 R_FreeTexture(r_bloomstate.texture_screen);
3089 r_bloomstate.texture_screen = NULL;
3090 r_bloomstate.screentexturewidth = screentexturewidth;
3091 r_bloomstate.screentextureheight = screentextureheight;
3092 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3093 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);
3095 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3097 if (r_bloomstate.texture_bloom)
3098 R_FreeTexture(r_bloomstate.texture_bloom);
3099 r_bloomstate.texture_bloom = NULL;
3100 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3101 r_bloomstate.bloomtextureheight = bloomtextureheight;
3102 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3103 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);
3106 // set up a texcoord array for the full resolution screen image
3107 // (we have to keep this around to copy back during final render)
3108 r_bloomstate.screentexcoord2f[0] = 0;
3109 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3110 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3111 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3112 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3113 r_bloomstate.screentexcoord2f[5] = 0;
3114 r_bloomstate.screentexcoord2f[6] = 0;
3115 r_bloomstate.screentexcoord2f[7] = 0;
3117 // set up a texcoord array for the reduced resolution bloom image
3118 // (which will be additive blended over the screen image)
3119 r_bloomstate.bloomtexcoord2f[0] = 0;
3120 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3121 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3122 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3123 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3124 r_bloomstate.bloomtexcoord2f[5] = 0;
3125 r_bloomstate.bloomtexcoord2f[6] = 0;
3126 r_bloomstate.bloomtexcoord2f[7] = 0;
3128 if (r_hdr.integer || r_bloom.integer)
3130 r_bloomstate.enabled = true;
3131 r_bloomstate.hdr = r_hdr.integer != 0;
3135 void R_Bloom_CopyBloomTexture(float colorscale)
3137 r_refdef.stats.bloom++;
3139 // scale down screen texture to the bloom texture size
3141 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3142 GL_BlendFunc(GL_ONE, GL_ZERO);
3143 GL_Color(colorscale, colorscale, colorscale, 1);
3144 // TODO: optimize with multitexture or GLSL
3145 R_SetupGenericShader(true);
3146 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3147 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3148 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3149 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3151 // we now have a bloom image in the framebuffer
3152 // copy it into the bloom image texture for later processing
3153 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3154 GL_ActiveTexture(0);
3156 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
3157 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3160 void R_Bloom_CopyHDRTexture(void)
3162 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3163 GL_ActiveTexture(0);
3165 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
3166 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3169 void R_Bloom_MakeTexture(void)
3172 float xoffset, yoffset, r, brighten;
3174 r_refdef.stats.bloom++;
3176 R_ResetViewRendering2D();
3177 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3178 R_Mesh_ColorPointer(NULL, 0, 0);
3179 R_SetupGenericShader(true);
3181 // we have a bloom image in the framebuffer
3183 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3185 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3188 r = bound(0, r_bloom_colorexponent.value / x, 1);
3189 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3190 GL_Color(r, r, r, 1);
3191 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3192 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3193 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3194 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3196 // copy the vertically blurred bloom view to a texture
3197 GL_ActiveTexture(0);
3199 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
3200 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3203 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3204 brighten = r_bloom_brighten.value;
3206 brighten *= r_hdr_range.value;
3207 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3208 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3210 for (dir = 0;dir < 2;dir++)
3212 // blend on at multiple vertical offsets to achieve a vertical blur
3213 // TODO: do offset blends using GLSL
3214 GL_BlendFunc(GL_ONE, GL_ZERO);
3215 for (x = -range;x <= range;x++)
3217 if (!dir){xoffset = 0;yoffset = x;}
3218 else {xoffset = x;yoffset = 0;}
3219 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3220 yoffset /= (float)r_bloomstate.bloomtextureheight;
3221 // compute a texcoord array with the specified x and y offset
3222 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3223 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3224 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3225 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3226 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3227 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3228 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3229 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3230 // this r value looks like a 'dot' particle, fading sharply to
3231 // black at the edges
3232 // (probably not realistic but looks good enough)
3233 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3234 //r = (dir ? 1.0f : brighten)/(range*2+1);
3235 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3236 GL_Color(r, r, r, 1);
3237 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3238 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3239 GL_BlendFunc(GL_ONE, GL_ONE);
3242 // copy the vertically blurred bloom view to a texture
3243 GL_ActiveTexture(0);
3245 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
3246 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3249 // apply subtract last
3250 // (just like it would be in a GLSL shader)
3251 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3253 GL_BlendFunc(GL_ONE, GL_ZERO);
3254 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3255 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3256 GL_Color(1, 1, 1, 1);
3257 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3258 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3260 GL_BlendFunc(GL_ONE, GL_ONE);
3261 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3262 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3263 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3264 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3265 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3266 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3267 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3269 // copy the darkened bloom view to a texture
3270 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3271 GL_ActiveTexture(0);
3273 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
3274 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3278 void R_HDR_RenderBloomTexture(void)
3280 int oldwidth, oldheight;
3281 float oldcolorscale;
3283 oldcolorscale = r_refdef.view.colorscale;
3284 oldwidth = r_refdef.view.width;
3285 oldheight = r_refdef.view.height;
3286 r_refdef.view.width = r_bloomstate.bloomwidth;
3287 r_refdef.view.height = r_bloomstate.bloomheight;
3289 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3290 // TODO: add exposure compensation features
3291 // TODO: add fp16 framebuffer support
3293 r_refdef.view.showdebug = false;
3294 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3296 R_ClearScreen(r_refdef.fogenabled);
3297 if (r_timereport_active)
3298 R_TimeReport("HDRclear");
3300 r_waterstate.numwaterplanes = 0;
3301 R_RenderScene(r_waterstate.enabled);
3302 r_refdef.view.showdebug = true;
3304 R_ResetViewRendering2D();
3306 R_Bloom_CopyHDRTexture();
3307 R_Bloom_MakeTexture();
3309 // restore the view settings
3310 r_refdef.view.width = oldwidth;
3311 r_refdef.view.height = oldheight;
3312 r_refdef.view.colorscale = oldcolorscale;
3314 R_ResetViewRendering3D();
3316 R_ClearScreen(r_refdef.fogenabled);
3317 if (r_timereport_active)
3318 R_TimeReport("viewclear");
3321 static void R_BlendView(void)
3323 if (r_bloomstate.texture_screen)
3325 // copy view into the screen texture
3326 R_ResetViewRendering2D();
3327 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3328 R_Mesh_ColorPointer(NULL, 0, 0);
3329 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3330 GL_ActiveTexture(0);CHECKGLERROR
3331 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
3332 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3335 if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3337 unsigned int permutation = (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0) | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0) | (r_glsl_postprocess_contrastboost.value != 1 ? SHADERPERMUTATION_CONTRASTBOOST : 0);
3339 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3341 // render simple bloom effect
3342 // copy the screen and shrink it and darken it for the bloom process
3343 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3344 // make the bloom texture
3345 R_Bloom_MakeTexture();
3348 R_ResetViewRendering2D();
3349 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3350 R_Mesh_ColorPointer(NULL, 0, 0);
3351 GL_Color(1, 1, 1, 1);
3352 GL_BlendFunc(GL_ONE, GL_ZERO);
3353 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3354 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3355 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3356 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3357 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3358 if (r_glsl_permutation->loc_TintColor >= 0)
3359 qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3360 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
3361 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_postprocess_contrastboost.value - 1);
3362 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3363 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3369 if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3371 // render high dynamic range bloom effect
3372 // the bloom texture was made earlier this render, so we just need to
3373 // blend it onto the screen...
3374 R_ResetViewRendering2D();
3375 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3376 R_Mesh_ColorPointer(NULL, 0, 0);
3377 R_SetupGenericShader(true);
3378 GL_Color(1, 1, 1, 1);
3379 GL_BlendFunc(GL_ONE, GL_ONE);
3380 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3381 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3382 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3383 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3385 else if (r_bloomstate.texture_bloom)
3387 // render simple bloom effect
3388 // copy the screen and shrink it and darken it for the bloom process
3389 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3390 // make the bloom texture
3391 R_Bloom_MakeTexture();
3392 // put the original screen image back in place and blend the bloom
3394 R_ResetViewRendering2D();
3395 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3396 R_Mesh_ColorPointer(NULL, 0, 0);
3397 GL_Color(1, 1, 1, 1);
3398 GL_BlendFunc(GL_ONE, GL_ZERO);
3399 // do both in one pass if possible
3400 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3401 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3402 if (r_textureunits.integer >= 2 && gl_combine.integer)
3404 R_SetupGenericTwoTextureShader(GL_ADD);
3405 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3406 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3410 R_SetupGenericShader(true);
3411 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3412 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3413 // now blend on the bloom texture
3414 GL_BlendFunc(GL_ONE, GL_ONE);
3415 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3416 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3418 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3419 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3421 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3423 // apply a color tint to the whole view
3424 R_ResetViewRendering2D();
3425 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3426 R_Mesh_ColorPointer(NULL, 0, 0);
3427 R_SetupGenericShader(false);
3428 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3429 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3430 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3434 void R_RenderScene(qboolean addwaterplanes);
3436 matrix4x4_t r_waterscrollmatrix;
3438 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3440 if (r_refdef.fog_density)
3442 r_refdef.fogcolor[0] = r_refdef.fog_red;
3443 r_refdef.fogcolor[1] = r_refdef.fog_green;
3444 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3448 VectorCopy(r_refdef.fogcolor, fogvec);
3449 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3451 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3452 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3453 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3454 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3456 // color.rgb *= ContrastBoost * SceneBrightness;
3457 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3458 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3459 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3460 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3465 void R_UpdateVariables(void)
3469 r_refdef.farclip = 4096;
3470 if (r_refdef.scene.worldmodel)
3471 r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3472 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3474 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3475 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3476 r_refdef.polygonfactor = 0;
3477 r_refdef.polygonoffset = 0;
3478 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3479 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3481 r_refdef.rtworld = r_shadow_realtime_world.integer;
3482 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3483 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3484 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3485 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3486 if (r_showsurfaces.integer)
3488 r_refdef.rtworld = false;
3489 r_refdef.rtworldshadows = false;
3490 r_refdef.rtdlight = false;
3491 r_refdef.rtdlightshadows = false;
3492 r_refdef.lightmapintensity = 0;
3495 if (gamemode == GAME_NEHAHRA)
3497 if (gl_fogenable.integer)
3499 r_refdef.oldgl_fogenable = true;
3500 r_refdef.fog_density = gl_fogdensity.value;
3501 r_refdef.fog_red = gl_fogred.value;
3502 r_refdef.fog_green = gl_foggreen.value;
3503 r_refdef.fog_blue = gl_fogblue.value;
3504 r_refdef.fog_alpha = 1;
3505 r_refdef.fog_start = 0;
3506 r_refdef.fog_end = gl_skyclip.value;
3508 else if (r_refdef.oldgl_fogenable)
3510 r_refdef.oldgl_fogenable = false;
3511 r_refdef.fog_density = 0;
3512 r_refdef.fog_red = 0;
3513 r_refdef.fog_green = 0;
3514 r_refdef.fog_blue = 0;
3515 r_refdef.fog_alpha = 0;
3516 r_refdef.fog_start = 0;
3517 r_refdef.fog_end = 0;
3521 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3522 r_refdef.fog_start = max(0, r_refdef.fog_start);
3523 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3525 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3527 if (r_refdef.fog_density)
3529 r_refdef.fogenabled = true;
3530 // this is the point where the fog reaches 0.9986 alpha, which we
3531 // consider a good enough cutoff point for the texture
3532 // (0.9986 * 256 == 255.6)
3533 if (r_fog_exp2.integer)
3534 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3536 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3537 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3538 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3539 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3540 // fog color was already set
3541 // update the fog texture
3542 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)
3543 R_BuildFogTexture();
3546 r_refdef.fogenabled = false;
3549 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3550 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3556 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3557 if( scenetype != r_currentscenetype ) {
3558 // store the old scenetype
3559 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3560 r_currentscenetype = scenetype;
3561 // move in the new scene
3562 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3571 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3573 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3574 if( scenetype == r_currentscenetype ) {
3575 return &r_refdef.scene;
3577 return &r_scenes_store[ scenetype ];
3586 void R_RenderView(void)
3588 if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
3589 return; //Host_Error ("R_RenderView: NULL worldmodel");
3591 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3593 // break apart the view matrix into vectors for various purposes
3594 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3595 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3596 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3597 VectorNegate(r_refdef.view.left, r_refdef.view.right);
3598 // make an inverted copy of the view matrix for tracking sprites
3599 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3601 R_Shadow_UpdateWorldLightSelection();
3603 R_Bloom_StartFrame();
3604 R_Water_StartFrame();
3607 if (r_timereport_active)
3608 R_TimeReport("viewsetup");
3610 R_ResetViewRendering3D();
3612 if (r_refdef.view.clear || r_refdef.fogenabled)
3614 R_ClearScreen(r_refdef.fogenabled);
3615 if (r_timereport_active)
3616 R_TimeReport("viewclear");
3618 r_refdef.view.clear = true;
3620 r_refdef.view.showdebug = true;
3622 // this produces a bloom texture to be used in R_BlendView() later
3624 R_HDR_RenderBloomTexture();
3626 r_waterstate.numwaterplanes = 0;
3627 R_RenderScene(r_waterstate.enabled);
3630 if (r_timereport_active)
3631 R_TimeReport("blendview");
3633 GL_Scissor(0, 0, vid.width, vid.height);
3634 GL_ScissorTest(false);
3638 extern void R_DrawLightningBeams (void);
3639 extern void VM_CL_AddPolygonsToMeshQueue (void);
3640 extern void R_DrawPortals (void);
3641 extern cvar_t cl_locs_show;
3642 static void R_DrawLocs(void);
3643 static void R_DrawEntityBBoxes(void);
3644 void R_RenderScene(qboolean addwaterplanes)
3646 r_refdef.stats.renders++;
3652 R_ResetViewRendering3D();
3655 if (r_timereport_active)
3656 R_TimeReport("watervis");
3658 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3660 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3661 if (r_timereport_active)
3662 R_TimeReport("waterworld");
3665 // don't let sound skip if going slow
3666 if (r_refdef.scene.extraupdate)
3669 R_DrawModelsAddWaterPlanes();
3670 if (r_timereport_active)
3671 R_TimeReport("watermodels");
3673 R_Water_ProcessPlanes();
3674 if (r_timereport_active)
3675 R_TimeReport("waterscenes");
3678 R_ResetViewRendering3D();
3680 // don't let sound skip if going slow
3681 if (r_refdef.scene.extraupdate)
3684 R_MeshQueue_BeginScene();
3689 if (r_timereport_active)
3690 R_TimeReport("visibility");
3692 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);
3694 if (cl.csqc_vidvars.drawworld)
3696 // don't let sound skip if going slow
3697 if (r_refdef.scene.extraupdate)
3700 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3702 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3703 if (r_timereport_active)
3704 R_TimeReport("worldsky");
3707 if (R_DrawBrushModelsSky() && r_timereport_active)
3708 R_TimeReport("bmodelsky");
3711 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3713 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3714 if (r_timereport_active)
3715 R_TimeReport("worlddepth");
3717 if (r_depthfirst.integer >= 2)
3719 R_DrawModelsDepth();
3720 if (r_timereport_active)
3721 R_TimeReport("modeldepth");
3724 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3726 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3727 if (r_timereport_active)
3728 R_TimeReport("world");
3731 // don't let sound skip if going slow
3732 if (r_refdef.scene.extraupdate)
3736 if (r_timereport_active)
3737 R_TimeReport("models");
3739 // don't let sound skip if going slow
3740 if (r_refdef.scene.extraupdate)
3743 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3745 R_DrawModelShadows();
3747 R_ResetViewRendering3D();
3749 // don't let sound skip if going slow
3750 if (r_refdef.scene.extraupdate)
3754 R_ShadowVolumeLighting(false);
3755 if (r_timereport_active)
3756 R_TimeReport("rtlights");
3758 // don't let sound skip if going slow
3759 if (r_refdef.scene.extraupdate)
3762 if (cl.csqc_vidvars.drawworld)
3764 R_DrawLightningBeams();
3765 if (r_timereport_active)
3766 R_TimeReport("lightning");
3769 if (r_timereport_active)
3770 R_TimeReport("decals");
3773 if (r_timereport_active)
3774 R_TimeReport("particles");
3777 if (r_timereport_active)
3778 R_TimeReport("explosions");
3781 R_SetupGenericShader(true);
3782 VM_CL_AddPolygonsToMeshQueue();
3784 if (r_refdef.view.showdebug)
3786 if (cl_locs_show.integer)
3789 if (r_timereport_active)
3790 R_TimeReport("showlocs");
3793 if (r_drawportals.integer)
3796 if (r_timereport_active)
3797 R_TimeReport("portals");
3800 if (r_showbboxes.value > 0)
3802 R_DrawEntityBBoxes();
3803 if (r_timereport_active)
3804 R_TimeReport("bboxes");
3808 R_SetupGenericShader(true);
3809 R_MeshQueue_RenderTransparent();
3810 if (r_timereport_active)
3811 R_TimeReport("drawtrans");
3813 R_SetupGenericShader(true);
3815 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))
3817 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
3818 if (r_timereport_active)
3819 R_TimeReport("worlddebug");
3820 R_DrawModelsDebug();
3821 if (r_timereport_active)
3822 R_TimeReport("modeldebug");
3825 R_SetupGenericShader(true);
3827 if (cl.csqc_vidvars.drawworld)
3830 if (r_timereport_active)
3831 R_TimeReport("coronas");
3834 // don't let sound skip if going slow
3835 if (r_refdef.scene.extraupdate)
3838 R_ResetViewRendering2D();
3841 static const int bboxelements[36] =
3851 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3854 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3855 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3856 GL_DepthMask(false);
3857 GL_DepthRange(0, 1);
3858 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3859 R_Mesh_Matrix(&identitymatrix);
3860 R_Mesh_ResetTextureState();
3862 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3863 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3864 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3865 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3866 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3867 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3868 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3869 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3870 R_FillColors(color4f, 8, cr, cg, cb, ca);
3871 if (r_refdef.fogenabled)
3873 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3875 f1 = FogPoint_World(v);
3877 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3878 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3879 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3882 R_Mesh_VertexPointer(vertex3f, 0, 0);
3883 R_Mesh_ColorPointer(color4f, 0, 0);
3884 R_Mesh_ResetTextureState();
3885 R_SetupGenericShader(false);
3886 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3889 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3893 prvm_edict_t *edict;
3894 // this function draws bounding boxes of server entities
3897 R_SetupGenericShader(false);
3899 for (i = 0;i < numsurfaces;i++)
3901 edict = PRVM_EDICT_NUM(surfacelist[i]);
3902 switch ((int)edict->fields.server->solid)
3904 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3905 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3906 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3907 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3908 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3909 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3911 color[3] *= r_showbboxes.value;
3912 color[3] = bound(0, color[3], 1);
3913 GL_DepthTest(!r_showdisabledepthtest.integer);
3914 GL_CullFace(r_refdef.view.cullface_front);
3915 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3920 static void R_DrawEntityBBoxes(void)
3923 prvm_edict_t *edict;
3925 // this function draws bounding boxes of server entities
3929 for (i = 0;i < prog->num_edicts;i++)
3931 edict = PRVM_EDICT_NUM(i);
3932 if (edict->priv.server->free)
3934 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3935 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3940 int nomodelelements[24] =
3952 float nomodelvertex3f[6*3] =
3962 float nomodelcolor4f[6*4] =
3964 0.0f, 0.0f, 0.5f, 1.0f,
3965 0.0f, 0.0f, 0.5f, 1.0f,
3966 0.0f, 0.5f, 0.0f, 1.0f,
3967 0.0f, 0.5f, 0.0f, 1.0f,
3968 0.5f, 0.0f, 0.0f, 1.0f,
3969 0.5f, 0.0f, 0.0f, 1.0f
3972 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3977 // this is only called once per entity so numsurfaces is always 1, and
3978 // surfacelist is always {0}, so this code does not handle batches
3979 R_Mesh_Matrix(&ent->matrix);
3981 if (ent->flags & EF_ADDITIVE)
3983 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3984 GL_DepthMask(false);
3986 else if (ent->alpha < 1)
3988 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3989 GL_DepthMask(false);
3993 GL_BlendFunc(GL_ONE, GL_ZERO);
3996 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3997 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3998 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3999 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4000 R_SetupGenericShader(false);
4001 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4002 if (r_refdef.fogenabled)
4005 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4006 R_Mesh_ColorPointer(color4f, 0, 0);
4007 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4008 f1 = FogPoint_World(org);
4010 for (i = 0, c = color4f;i < 6;i++, c += 4)
4012 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4013 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4014 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4018 else if (ent->alpha != 1)
4020 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4021 R_Mesh_ColorPointer(color4f, 0, 0);
4022 for (i = 0, c = color4f;i < 6;i++, c += 4)
4026 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4027 R_Mesh_ResetTextureState();
4028 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
4031 void R_DrawNoModel(entity_render_t *ent)
4034 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4035 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4036 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4038 // R_DrawNoModelCallback(ent, 0);
4041 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4043 vec3_t right1, right2, diff, normal;
4045 VectorSubtract (org2, org1, normal);
4047 // calculate 'right' vector for start
4048 VectorSubtract (r_refdef.view.origin, org1, diff);
4049 CrossProduct (normal, diff, right1);
4050 VectorNormalize (right1);
4052 // calculate 'right' vector for end
4053 VectorSubtract (r_refdef.view.origin, org2, diff);
4054 CrossProduct (normal, diff, right2);
4055 VectorNormalize (right2);
4057 vert[ 0] = org1[0] + width * right1[0];
4058 vert[ 1] = org1[1] + width * right1[1];
4059 vert[ 2] = org1[2] + width * right1[2];
4060 vert[ 3] = org1[0] - width * right1[0];
4061 vert[ 4] = org1[1] - width * right1[1];
4062 vert[ 5] = org1[2] - width * right1[2];
4063 vert[ 6] = org2[0] - width * right2[0];
4064 vert[ 7] = org2[1] - width * right2[1];
4065 vert[ 8] = org2[2] - width * right2[2];
4066 vert[ 9] = org2[0] + width * right2[0];
4067 vert[10] = org2[1] + width * right2[1];
4068 vert[11] = org2[2] + width * right2[2];
4071 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4073 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)
4078 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4079 fog = FogPoint_World(origin);
4081 R_Mesh_Matrix(&identitymatrix);
4082 GL_BlendFunc(blendfunc1, blendfunc2);
4088 GL_CullFace(r_refdef.view.cullface_front);
4091 GL_CullFace(r_refdef.view.cullface_back);
4092 GL_CullFace(GL_NONE);
4094 GL_DepthMask(false);
4095 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4096 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4097 GL_DepthTest(!depthdisable);
4099 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4100 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4101 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4102 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4103 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4104 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4105 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4106 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4107 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4108 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4109 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4110 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4112 R_Mesh_VertexPointer(vertex3f, 0, 0);
4113 R_Mesh_ColorPointer(NULL, 0, 0);
4114 R_Mesh_ResetTextureState();
4115 R_SetupGenericShader(true);
4116 R_Mesh_TexBind(0, R_GetTexture(texture));
4117 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4118 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4119 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4120 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4122 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4124 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4125 GL_BlendFunc(blendfunc1, GL_ONE);
4127 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4128 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4132 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4137 VectorSet(v, x, y, z);
4138 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4139 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4141 if (i == mesh->numvertices)
4143 if (mesh->numvertices < mesh->maxvertices)
4145 VectorCopy(v, vertex3f);
4146 mesh->numvertices++;
4148 return mesh->numvertices;
4154 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4158 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4159 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4160 e = mesh->element3i + mesh->numtriangles * 3;
4161 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4163 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4164 if (mesh->numtriangles < mesh->maxtriangles)
4169 mesh->numtriangles++;
4171 element[1] = element[2];
4175 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4179 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4180 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4181 e = mesh->element3i + mesh->numtriangles * 3;
4182 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4184 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4185 if (mesh->numtriangles < mesh->maxtriangles)
4190 mesh->numtriangles++;
4192 element[1] = element[2];
4196 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4197 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4199 int planenum, planenum2;
4202 mplane_t *plane, *plane2;
4204 double temppoints[2][256*3];
4205 // figure out how large a bounding box we need to properly compute this brush
4207 for (w = 0;w < numplanes;w++)
4208 maxdist = max(maxdist, planes[w].dist);
4209 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4210 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4211 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4215 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4216 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4218 if (planenum2 == planenum)
4220 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);
4223 if (tempnumpoints < 3)
4225 // generate elements forming a triangle fan for this polygon
4226 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4230 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)
4232 texturelayer_t *layer;
4233 layer = t->currentlayers + t->currentnumlayers++;
4235 layer->depthmask = depthmask;
4236 layer->blendfunc1 = blendfunc1;
4237 layer->blendfunc2 = blendfunc2;
4238 layer->texture = texture;
4239 layer->texmatrix = *matrix;
4240 layer->color[0] = r * r_refdef.view.colorscale;
4241 layer->color[1] = g * r_refdef.view.colorscale;
4242 layer->color[2] = b * r_refdef.view.colorscale;
4243 layer->color[3] = a;
4246 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4249 index = parms[2] + r_refdef.scene.time * parms[3];
4250 index -= floor(index);
4254 case Q3WAVEFUNC_NONE:
4255 case Q3WAVEFUNC_NOISE:
4256 case Q3WAVEFUNC_COUNT:
4259 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4260 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4261 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4262 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4263 case Q3WAVEFUNC_TRIANGLE:
4265 f = index - floor(index);
4276 return (float)(parms[0] + parms[1] * f);
4279 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4282 model_t *model = ent->model;
4285 q3shaderinfo_layer_tcmod_t *tcmod;
4287 // switch to an alternate material if this is a q1bsp animated material
4289 texture_t *texture = t;
4290 int s = ent->skinnum;
4291 if ((unsigned int)s >= (unsigned int)model->numskins)
4293 if (model->skinscenes)
4295 if (model->skinscenes[s].framecount > 1)
4296 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4298 s = model->skinscenes[s].firstframe;
4301 t = t + s * model->num_surfaces;
4304 // use an alternate animation if the entity's frame is not 0,
4305 // and only if the texture has an alternate animation
4306 if (ent->frame2 != 0 && t->anim_total[1])
4307 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4309 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4311 texture->currentframe = t;
4314 // update currentskinframe to be a qw skin or animation frame
4315 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4317 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4319 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4320 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4321 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);
4323 t->currentskinframe = r_qwskincache_skinframe[i];
4324 if (t->currentskinframe == NULL)
4325 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4327 else if (t->numskinframes >= 2)
4328 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4329 if (t->backgroundnumskinframes >= 2)
4330 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4332 t->currentmaterialflags = t->basematerialflags;
4333 t->currentalpha = ent->alpha;
4334 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4336 t->currentalpha *= r_wateralpha.value;
4338 * FIXME what is this supposed to do?
4339 // if rendering refraction/reflection, disable transparency
4340 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4341 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4344 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled)
4345 t->currentalpha *= t->r_water_wateralpha;
4346 if(!r_waterstate.enabled)
4347 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4348 if (!(ent->flags & RENDER_LIGHT))
4349 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4350 else if (rsurface.modeltexcoordlightmap2f == NULL)
4352 // pick a model lighting mode
4353 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4354 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4356 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4358 if (ent->effects & EF_ADDITIVE)
4359 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4360 else if (t->currentalpha < 1)
4361 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4362 if (ent->effects & EF_DOUBLESIDED)
4363 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4364 if (ent->effects & EF_NODEPTHTEST)
4365 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4366 if (ent->flags & RENDER_VIEWMODEL)
4367 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4368 if (t->backgroundnumskinframes)
4369 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4370 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4372 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4373 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4376 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4378 // there is no tcmod
4379 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4380 t->currenttexmatrix = r_waterscrollmatrix;
4382 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4385 switch(tcmod->tcmod)
4389 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4390 matrix = r_waterscrollmatrix;
4392 matrix = identitymatrix;
4394 case Q3TCMOD_ENTITYTRANSLATE:
4395 // this is used in Q3 to allow the gamecode to control texcoord
4396 // scrolling on the entity, which is not supported in darkplaces yet.
4397 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4399 case Q3TCMOD_ROTATE:
4400 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4401 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4402 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4405 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4407 case Q3TCMOD_SCROLL:
4408 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4410 case Q3TCMOD_STRETCH:
4411 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4412 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4414 case Q3TCMOD_TRANSFORM:
4415 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4416 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4417 VectorSet(tcmat + 6, 0 , 0 , 1);
4418 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4419 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4421 case Q3TCMOD_TURBULENT:
4422 // this is handled in the RSurf_PrepareVertices function
4423 matrix = identitymatrix;
4426 // either replace or concatenate the transformation
4428 t->currenttexmatrix = matrix;
4431 matrix4x4_t temp = t->currenttexmatrix;
4432 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4436 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4437 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4438 t->glosstexture = r_texture_black;
4439 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4440 t->backgroundglosstexture = r_texture_black;
4441 t->specularpower = r_shadow_glossexponent.value;
4442 // TODO: store reference values for these in the texture?
4443 t->specularscale = 0;
4444 if (r_shadow_gloss.integer > 0)
4446 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4448 if (r_shadow_glossintensity.value > 0)
4450 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4451 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4452 t->specularscale = r_shadow_glossintensity.value;
4455 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4457 t->glosstexture = r_texture_white;
4458 t->backgroundglosstexture = r_texture_white;
4459 t->specularscale = r_shadow_gloss2intensity.value;
4463 // lightmaps mode looks bad with dlights using actual texturing, so turn
4464 // off the colormap and glossmap, but leave the normalmap on as it still
4465 // accurately represents the shading involved
4466 if (gl_lightmaps.integer)
4468 t->basetexture = r_texture_grey128;
4469 t->backgroundbasetexture = NULL;
4470 t->specularscale = 0;
4471 t->currentmaterialflags &= ~(MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_WATERALPHA | MATERIALFLAG_WATER | MATERIALFLAG_SKY | MATERIALFLAG_ALPHATEST | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4472 t->currentmaterialflags |= MATERIALFLAG_WALL;
4475 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4476 VectorClear(t->dlightcolor);
4477 t->currentnumlayers = 0;
4478 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4480 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4482 int blendfunc1, blendfunc2, depthmask;
4483 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4485 blendfunc1 = GL_SRC_ALPHA;
4486 blendfunc2 = GL_ONE;
4488 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4490 blendfunc1 = GL_SRC_ALPHA;
4491 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4493 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4495 blendfunc1 = t->customblendfunc[0];
4496 blendfunc2 = t->customblendfunc[1];
4500 blendfunc1 = GL_ONE;
4501 blendfunc2 = GL_ZERO;
4503 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4504 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4507 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4508 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4509 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4511 // fullbright is not affected by r_refdef.lightmapintensity
4512 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]);
4513 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4514 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]);
4515 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4516 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]);
4520 vec3_t ambientcolor;
4522 // set the color tint used for lights affecting this surface
4523 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4525 // q3bsp has no lightmap updates, so the lightstylevalue that
4526 // would normally be baked into the lightmap must be
4527 // applied to the color
4528 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4529 if (ent->model->type == mod_brushq3)
4530 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4531 colorscale *= r_refdef.lightmapintensity;
4532 VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4533 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4534 // basic lit geometry
4535 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]);
4536 // add pants/shirt if needed
4537 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4538 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]);
4539 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4540 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]);
4541 // now add ambient passes if needed
4542 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4544 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]);
4545 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4546 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]);
4547 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4548 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]);
4551 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4552 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]);
4553 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4555 // if this is opaque use alpha blend which will darken the earlier
4558 // if this is an alpha blended material, all the earlier passes
4559 // were darkened by fog already, so we only need to add the fog
4560 // color ontop through the fog mask texture
4562 // if this is an additive blended material, all the earlier passes
4563 // were darkened by fog already, and we should not add fog color
4564 // (because the background was not darkened, there is no fog color
4565 // that was lost behind it).
4566 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]);
4573 void R_UpdateAllTextureInfo(entity_render_t *ent)
4577 for (i = 0;i < ent->model->num_texturesperskin;i++)
4578 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4581 rsurfacestate_t rsurface;
4583 void R_Mesh_ResizeArrays(int newvertices)
4586 if (rsurface.array_size >= newvertices)
4588 if (rsurface.array_modelvertex3f)
4589 Mem_Free(rsurface.array_modelvertex3f);
4590 rsurface.array_size = (newvertices + 1023) & ~1023;
4591 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4592 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4593 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4594 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4595 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4596 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4597 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4598 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4599 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4600 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4601 rsurface.array_color4f = base + rsurface.array_size * 27;
4602 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4605 void RSurf_ActiveWorldEntity(void)
4607 model_t *model = r_refdef.scene.worldmodel;
4608 if (rsurface.array_size < model->surfmesh.num_vertices)
4609 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4610 rsurface.matrix = identitymatrix;
4611 rsurface.inversematrix = identitymatrix;
4612 R_Mesh_Matrix(&identitymatrix);
4613 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4614 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4615 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4616 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4617 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4618 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4619 rsurface.frameblend[0].frame = 0;
4620 rsurface.frameblend[0].lerp = 1;
4621 rsurface.frameblend[1].frame = 0;
4622 rsurface.frameblend[1].lerp = 0;
4623 rsurface.frameblend[2].frame = 0;
4624 rsurface.frameblend[2].lerp = 0;
4625 rsurface.frameblend[3].frame = 0;
4626 rsurface.frameblend[3].lerp = 0;
4627 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4628 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4629 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4630 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4631 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4632 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4633 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4634 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4635 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4636 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4637 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4638 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4639 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4640 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4641 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4642 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4643 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4644 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4645 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4646 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4647 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4648 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4649 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4650 rsurface.modelelement3i = model->surfmesh.data_element3i;
4651 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4652 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4653 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4654 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4655 rsurface.modelsurfaces = model->data_surfaces;
4656 rsurface.generatedvertex = false;
4657 rsurface.vertex3f = rsurface.modelvertex3f;
4658 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4659 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4660 rsurface.svector3f = rsurface.modelsvector3f;
4661 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4662 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4663 rsurface.tvector3f = rsurface.modeltvector3f;
4664 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4665 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4666 rsurface.normal3f = rsurface.modelnormal3f;
4667 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4668 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4669 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4672 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4674 model_t *model = ent->model;
4675 if (rsurface.array_size < model->surfmesh.num_vertices)
4676 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4677 rsurface.matrix = ent->matrix;
4678 rsurface.inversematrix = ent->inversematrix;
4679 R_Mesh_Matrix(&rsurface.matrix);
4680 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4681 rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4682 rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4683 rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4684 rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4685 rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4686 rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4687 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4688 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4689 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4690 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4691 rsurface.frameblend[0] = ent->frameblend[0];
4692 rsurface.frameblend[1] = ent->frameblend[1];
4693 rsurface.frameblend[2] = ent->frameblend[2];
4694 rsurface.frameblend[3] = ent->frameblend[3];
4695 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4696 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4697 if (ent->model->brush.submodel)
4699 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4700 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4702 if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4706 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4707 rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4708 rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4709 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4710 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4712 else if (wantnormals)
4714 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4715 rsurface.modelsvector3f = NULL;
4716 rsurface.modeltvector3f = NULL;
4717 rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4718 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4722 rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4723 rsurface.modelsvector3f = NULL;
4724 rsurface.modeltvector3f = NULL;
4725 rsurface.modelnormal3f = NULL;
4726 Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4728 rsurface.modelvertex3f_bufferobject = 0;
4729 rsurface.modelvertex3f_bufferoffset = 0;
4730 rsurface.modelsvector3f_bufferobject = 0;
4731 rsurface.modelsvector3f_bufferoffset = 0;
4732 rsurface.modeltvector3f_bufferobject = 0;
4733 rsurface.modeltvector3f_bufferoffset = 0;
4734 rsurface.modelnormal3f_bufferobject = 0;
4735 rsurface.modelnormal3f_bufferoffset = 0;
4736 rsurface.generatedvertex = true;
4740 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4741 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4742 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4743 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4744 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4745 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4746 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4747 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4748 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4749 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4750 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4751 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4752 rsurface.generatedvertex = false;
4754 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4755 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4756 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4757 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4758 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4759 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4760 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4761 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4762 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4763 rsurface.modelelement3i = model->surfmesh.data_element3i;
4764 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4765 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4766 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4767 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4768 rsurface.modelsurfaces = model->data_surfaces;
4769 rsurface.vertex3f = rsurface.modelvertex3f;
4770 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4771 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4772 rsurface.svector3f = rsurface.modelsvector3f;
4773 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4774 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4775 rsurface.tvector3f = rsurface.modeltvector3f;
4776 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4777 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4778 rsurface.normal3f = rsurface.modelnormal3f;
4779 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4780 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4781 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4784 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4785 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4788 int texturesurfaceindex;
4793 const float *v1, *in_tc;
4795 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4797 q3shaderinfo_deform_t *deform;
4798 // 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
4799 if (rsurface.generatedvertex)
4801 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4802 generatenormals = true;
4803 for (i = 0;i < Q3MAXDEFORMS;i++)
4805 if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4807 generatetangents = true;
4808 generatenormals = true;
4810 if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4811 generatenormals = true;
4813 if (generatenormals && !rsurface.modelnormal3f)
4815 rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4816 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4817 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4818 Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4820 if (generatetangents && !rsurface.modelsvector3f)
4822 rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4823 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4824 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4825 rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4826 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4827 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4828 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);
4831 rsurface.vertex3f = rsurface.modelvertex3f;
4832 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4833 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4834 rsurface.svector3f = rsurface.modelsvector3f;
4835 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4836 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4837 rsurface.tvector3f = rsurface.modeltvector3f;
4838 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4839 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4840 rsurface.normal3f = rsurface.modelnormal3f;
4841 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4842 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4843 // if vertices are deformed (sprite flares and things in maps, possibly
4844 // water waves, bulges and other deformations), generate them into
4845 // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4846 // (may be static model data or generated data for an animated model, or
4847 // the previous deform pass)
4848 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4850 switch (deform->deform)
4853 case Q3DEFORM_PROJECTIONSHADOW:
4854 case Q3DEFORM_TEXT0:
4855 case Q3DEFORM_TEXT1:
4856 case Q3DEFORM_TEXT2:
4857 case Q3DEFORM_TEXT3:
4858 case Q3DEFORM_TEXT4:
4859 case Q3DEFORM_TEXT5:
4860 case Q3DEFORM_TEXT6:
4861 case Q3DEFORM_TEXT7:
4864 case Q3DEFORM_AUTOSPRITE:
4865 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4866 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4867 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4868 VectorNormalize(newforward);
4869 VectorNormalize(newright);
4870 VectorNormalize(newup);
4871 // make deformed versions of only the model vertices used by the specified surfaces
4872 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4874 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4875 // a single autosprite surface can contain multiple sprites...
4876 for (j = 0;j < surface->num_vertices - 3;j += 4)
4878 VectorClear(center);
4879 for (i = 0;i < 4;i++)
4880 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4881 VectorScale(center, 0.25f, center);
4882 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, forward);
4883 VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4884 VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4885 for (i = 0;i < 4;i++)
4887 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4888 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4891 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);
4892 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);
4894 rsurface.vertex3f = rsurface.array_deformedvertex3f;
4895 rsurface.vertex3f_bufferobject = 0;
4896 rsurface.vertex3f_bufferoffset = 0;
4897 rsurface.svector3f = rsurface.array_deformedsvector3f;
4898 rsurface.svector3f_bufferobject = 0;
4899 rsurface.svector3f_bufferoffset = 0;
4900 rsurface.tvector3f = rsurface.array_deformedtvector3f;
4901 rsurface.tvector3f_bufferobject = 0;
4902 rsurface.tvector3f_bufferoffset = 0;
4903 rsurface.normal3f = rsurface.array_deformednormal3f;
4904 rsurface.normal3f_bufferobject = 0;
4905 rsurface.normal3f_bufferoffset = 0;
4907 case Q3DEFORM_AUTOSPRITE2:
4908 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4909 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4910 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4911 VectorNormalize(newforward);
4912 VectorNormalize(newright);
4913 VectorNormalize(newup);
4914 // make deformed versions of only the model vertices used by the specified surfaces
4915 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4917 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4918 const float *v1, *v2;
4928 memset(shortest, 0, sizeof(shortest));
4929 // a single autosprite surface can contain multiple sprites...
4930 for (j = 0;j < surface->num_vertices - 3;j += 4)
4932 VectorClear(center);
4933 for (i = 0;i < 4;i++)
4934 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4935 VectorScale(center, 0.25f, center);
4936 // find the two shortest edges, then use them to define the
4937 // axis vectors for rotating around the central axis
4938 for (i = 0;i < 6;i++)
4940 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4941 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4943 Debug_PolygonBegin(NULL, 0);
4944 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4945 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);
4946 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4949 l = VectorDistance2(v1, v2);
4950 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4952 l += (1.0f / 1024.0f);
4953 if (shortest[0].length2 > l || i == 0)
4955 shortest[1] = shortest[0];
4956 shortest[0].length2 = l;
4957 shortest[0].v1 = v1;
4958 shortest[0].v2 = v2;
4960 else if (shortest[1].length2 > l || i == 1)
4962 shortest[1].length2 = l;
4963 shortest[1].v1 = v1;
4964 shortest[1].v2 = v2;
4967 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4968 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4970 Debug_PolygonBegin(NULL, 0);
4971 Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4972 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);
4973 Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4976 // this calculates the right vector from the shortest edge
4977 // and the up vector from the edge midpoints
4978 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4979 VectorNormalize(right);
4980 VectorSubtract(end, start, up);
4981 VectorNormalize(up);
4982 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4983 //VectorSubtract(rsurface.modelorg, center, forward);
4984 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
4985 VectorNegate(forward, forward);
4986 VectorReflect(forward, 0, up, forward);
4987 VectorNormalize(forward);
4988 CrossProduct(up, forward, newright);
4989 VectorNormalize(newright);
4991 Debug_PolygonBegin(NULL, 0);
4992 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);
4993 Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4994 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
4998 Debug_PolygonBegin(NULL, 0);
4999 Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
5000 Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
5001 Debug_PolygonVertex(center[0] + up [0] * 8, center[1] + up [1] * 8, center[2] + up [2] * 8, 0, 0, 0, 0, 1, 1);
5004 // rotate the quad around the up axis vector, this is made
5005 // especially easy by the fact we know the quad is flat,
5006 // so we only have to subtract the center position and
5007 // measure distance along the right vector, and then
5008 // multiply that by the newright vector and add back the
5010 // we also need to subtract the old position to undo the
5011 // displacement from the center, which we do with a
5012 // DotProduct, the subtraction/addition of center is also
5013 // optimized into DotProducts here
5014 l = DotProduct(right, center);
5015 for (i = 0;i < 4;i++)
5017 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5018 f = DotProduct(right, v1) - l;
5019 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5022 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);
5023 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);
5025 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5026 rsurface.vertex3f_bufferobject = 0;
5027 rsurface.vertex3f_bufferoffset = 0;
5028 rsurface.svector3f = rsurface.array_deformedsvector3f;
5029 rsurface.svector3f_bufferobject = 0;
5030 rsurface.svector3f_bufferoffset = 0;
5031 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5032 rsurface.tvector3f_bufferobject = 0;
5033 rsurface.tvector3f_bufferoffset = 0;
5034 rsurface.normal3f = rsurface.array_deformednormal3f;
5035 rsurface.normal3f_bufferobject = 0;
5036 rsurface.normal3f_bufferoffset = 0;
5038 case Q3DEFORM_NORMAL:
5039 // deform the normals to make reflections wavey
5040 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5042 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5043 for (j = 0;j < surface->num_vertices;j++)
5046 float *normal = (rsurface.array_deformednormal3f + 3 * surface->num_firstvertex) + j*3;
5047 VectorScale((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5048 VectorCopy((rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, normal);
5049 normal[0] += deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5050 normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5051 normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5052 VectorNormalize(normal);
5054 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);
5056 rsurface.svector3f = rsurface.array_deformedsvector3f;
5057 rsurface.svector3f_bufferobject = 0;
5058 rsurface.svector3f_bufferoffset = 0;
5059 rsurface.tvector3f = rsurface.array_deformedtvector3f;
5060 rsurface.tvector3f_bufferobject = 0;
5061 rsurface.tvector3f_bufferoffset = 0;
5062 rsurface.normal3f = rsurface.array_deformednormal3f;
5063 rsurface.normal3f_bufferobject = 0;
5064 rsurface.normal3f_bufferoffset = 0;
5067 // deform vertex array to make wavey water and flags and such
5068 waveparms[0] = deform->waveparms[0];
5069 waveparms[1] = deform->waveparms[1];
5070 waveparms[2] = deform->waveparms[2];
5071 waveparms[3] = deform->waveparms[3];
5072 // this is how a divisor of vertex influence on deformation
5073 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5074 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5075 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5077 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5078 for (j = 0;j < surface->num_vertices;j++)
5080 float *vertex = (rsurface.array_deformedvertex3f + 3 * surface->num_firstvertex) + j*3;
5081 VectorCopy((rsurface.vertex3f + 3 * surface->num_firstvertex) + j*3, vertex);
5082 // if the wavefunc depends on time, evaluate it per-vertex
5085 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5086 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5088 VectorMA(vertex, scale, (rsurface.normal3f + 3 * surface->num_firstvertex) + j*3, vertex);
5091 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5092 rsurface.vertex3f_bufferobject = 0;
5093 rsurface.vertex3f_bufferoffset = 0;
5095 case Q3DEFORM_BULGE:
5096 // deform vertex array to make the surface have moving bulges
5097 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5099 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5100 for (j = 0;j < surface->num_vertices;j++)
5102 scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5103 VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5106 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5107 rsurface.vertex3f_bufferobject = 0;
5108 rsurface.vertex3f_bufferoffset = 0;
5111 // deform vertex array
5112 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5113 VectorScale(deform->parms, scale, waveparms);
5114 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5116 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5117 for (j = 0;j < surface->num_vertices;j++)
5118 VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5120 rsurface.vertex3f = rsurface.array_deformedvertex3f;
5121 rsurface.vertex3f_bufferobject = 0;
5122 rsurface.vertex3f_bufferoffset = 0;
5126 // generate texcoords based on the chosen texcoord source
5127 switch(rsurface.texture->tcgen.tcgen)
5130 case Q3TCGEN_TEXTURE:
5131 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
5132 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordtexture2f_bufferobject;
5133 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
5135 case Q3TCGEN_LIGHTMAP:
5136 rsurface.texcoordtexture2f = rsurface.modeltexcoordlightmap2f;
5137 rsurface.texcoordtexture2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5138 rsurface.texcoordtexture2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5140 case Q3TCGEN_VECTOR:
5141 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5143 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5144 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)
5146 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5147 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5150 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5151 rsurface.texcoordtexture2f_bufferobject = 0;
5152 rsurface.texcoordtexture2f_bufferoffset = 0;
5154 case Q3TCGEN_ENVIRONMENT:
5155 // make environment reflections using a spheremap
5156 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5158 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5159 const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5160 const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5161 float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5162 for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5164 float l, d, eyedir[3];
5165 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5166 l = 0.5f / VectorLength(eyedir);
5167 d = DotProduct(normal, eyedir)*2;
5168 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5169 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5172 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5173 rsurface.texcoordtexture2f_bufferobject = 0;
5174 rsurface.texcoordtexture2f_bufferoffset = 0;
5177 // the only tcmod that needs software vertex processing is turbulent, so
5178 // check for it here and apply the changes if needed
5179 // and we only support that as the first one
5180 // (handling a mixture of turbulent and other tcmods would be problematic
5181 // without punting it entirely to a software path)
5182 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5184 amplitude = rsurface.texture->tcmods[0].parms[1];
5185 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5186 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5188 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5189 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)
5191 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5192 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5195 rsurface.texcoordtexture2f = rsurface.array_generatedtexcoordtexture2f;
5196 rsurface.texcoordtexture2f_bufferobject = 0;
5197 rsurface.texcoordtexture2f_bufferoffset = 0;
5199 rsurface.texcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
5200 rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5201 rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5202 R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5205 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5208 const msurface_t *surface = texturesurfacelist[0];
5209 const msurface_t *surface2;
5214 // TODO: lock all array ranges before render, rather than on each surface
5215 if (texturenumsurfaces == 1)
5217 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5218 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5220 else if (r_batchmode.integer == 2)
5222 #define MAXBATCHTRIANGLES 4096
5223 int batchtriangles = 0;
5224 int batchelements[MAXBATCHTRIANGLES*3];
5225 for (i = 0;i < texturenumsurfaces;i = j)
5227 surface = texturesurfacelist[i];
5229 if (surface->num_triangles > MAXBATCHTRIANGLES)
5231 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5234 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5235 batchtriangles = surface->num_triangles;
5236 firstvertex = surface->num_firstvertex;
5237 endvertex = surface->num_firstvertex + surface->num_vertices;
5238 for (;j < texturenumsurfaces;j++)
5240 surface2 = texturesurfacelist[j];
5241 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5243 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5244 batchtriangles += surface2->num_triangles;
5245 firstvertex = min(firstvertex, surface2->num_firstvertex);
5246 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5248 surface2 = texturesurfacelist[j-1];
5249 numvertices = endvertex - firstvertex;
5250 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5253 else if (r_batchmode.integer == 1)
5255 for (i = 0;i < texturenumsurfaces;i = j)
5257 surface = texturesurfacelist[i];
5258 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5259 if (texturesurfacelist[j] != surface2)
5261 surface2 = texturesurfacelist[j-1];
5262 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5263 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5264 GL_LockArrays(surface->num_firstvertex, numvertices);
5265 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5270 for (i = 0;i < texturenumsurfaces;i++)
5272 surface = texturesurfacelist[i];
5273 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5274 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5279 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5281 int i, planeindex, vertexindex;
5285 r_waterstate_waterplane_t *p, *bestp;
5286 msurface_t *surface;
5287 if (r_waterstate.renderingscene)
5289 for (i = 0;i < texturenumsurfaces;i++)
5291 surface = texturesurfacelist[i];
5292 if (lightmaptexunit >= 0)
5293 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5294 if (deluxemaptexunit >= 0)
5295 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5296 // pick the closest matching water plane
5299 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5302 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5304 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5305 d += fabs(PlaneDiff(vert, &p->plane));
5307 if (bestd > d || !bestp)
5315 if (refractiontexunit >= 0)
5316 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5317 if (reflectiontexunit >= 0)
5318 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5322 if (refractiontexunit >= 0)
5323 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5324 if (reflectiontexunit >= 0)
5325 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5327 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5328 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5332 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5336 const msurface_t *surface = texturesurfacelist[0];
5337 const msurface_t *surface2;
5342 // TODO: lock all array ranges before render, rather than on each surface
5343 if (texturenumsurfaces == 1)
5345 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5346 if (deluxemaptexunit >= 0)
5347 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5348 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5349 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5351 else if (r_batchmode.integer == 2)
5353 #define MAXBATCHTRIANGLES 4096
5354 int batchtriangles = 0;
5355 int batchelements[MAXBATCHTRIANGLES*3];
5356 for (i = 0;i < texturenumsurfaces;i = j)
5358 surface = texturesurfacelist[i];
5359 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5360 if (deluxemaptexunit >= 0)
5361 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5363 if (surface->num_triangles > MAXBATCHTRIANGLES)
5365 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5368 memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5369 batchtriangles = surface->num_triangles;
5370 firstvertex = surface->num_firstvertex;
5371 endvertex = surface->num_firstvertex + surface->num_vertices;
5372 for (;j < texturenumsurfaces;j++)
5374 surface2 = texturesurfacelist[j];
5375 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5377 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5378 batchtriangles += surface2->num_triangles;
5379 firstvertex = min(firstvertex, surface2->num_firstvertex);
5380 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5382 surface2 = texturesurfacelist[j-1];
5383 numvertices = endvertex - firstvertex;
5384 R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5387 else if (r_batchmode.integer == 1)
5390 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5391 for (i = 0;i < texturenumsurfaces;i = j)
5393 surface = texturesurfacelist[i];
5394 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5395 if (texturesurfacelist[j] != surface2)
5397 Con_Printf(" %i", j - i);
5400 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5402 for (i = 0;i < texturenumsurfaces;i = j)
5404 surface = texturesurfacelist[i];
5405 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5406 if (deluxemaptexunit >= 0)
5407 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5408 for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5409 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5412 Con_Printf(" %i", j - i);
5414 surface2 = texturesurfacelist[j-1];
5415 numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5416 numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5417 GL_LockArrays(surface->num_firstvertex, numvertices);
5418 R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5426 for (i = 0;i < texturenumsurfaces;i++)
5428 surface = texturesurfacelist[i];
5429 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5430 if (deluxemaptexunit >= 0)
5431 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5432 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5433 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5438 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5441 int texturesurfaceindex;
5442 if (r_showsurfaces.integer == 2)
5444 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5446 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5447 for (j = 0;j < surface->num_triangles;j++)
5449 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5450 GL_Color(f, f, f, 1);
5451 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface.modelelement3i + 3 * (j + surface->num_firsttriangle)), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
5457 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5459 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5460 int k = (int)(((size_t)surface) / sizeof(msurface_t));
5461 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);
5462 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5463 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5468 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5470 int texturesurfaceindex;
5474 if (rsurface.lightmapcolor4f)
5476 // generate color arrays for the surfaces in this list
5477 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5479 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5480 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)
5482 f = FogPoint_Model(v);
5492 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5494 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5495 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)
5497 f = FogPoint_Model(v);
5505 rsurface.lightmapcolor4f = rsurface.array_color4f;
5506 rsurface.lightmapcolor4f_bufferobject = 0;
5507 rsurface.lightmapcolor4f_bufferoffset = 0;
5510 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5512 int texturesurfaceindex;
5515 if (!rsurface.lightmapcolor4f)
5517 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5519 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5520 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)
5528 rsurface.lightmapcolor4f = rsurface.array_color4f;
5529 rsurface.lightmapcolor4f_bufferobject = 0;
5530 rsurface.lightmapcolor4f_bufferoffset = 0;
5533 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5536 rsurface.lightmapcolor4f = NULL;
5537 rsurface.lightmapcolor4f_bufferobject = 0;
5538 rsurface.lightmapcolor4f_bufferoffset = 0;
5539 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5540 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5541 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5542 GL_Color(r, g, b, a);
5543 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5546 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5548 // TODO: optimize applyfog && applycolor case
5549 // just apply fog if necessary, and tint the fog color array if necessary
5550 rsurface.lightmapcolor4f = NULL;
5551 rsurface.lightmapcolor4f_bufferobject = 0;
5552 rsurface.lightmapcolor4f_bufferoffset = 0;
5553 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5554 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5555 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5556 GL_Color(r, g, b, a);
5557 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5560 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5562 int texturesurfaceindex;
5566 if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5568 // generate color arrays for the surfaces in this list
5569 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5571 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5572 for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5574 if (surface->lightmapinfo->samples)
5576 const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5577 float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5578 VectorScale(lm, scale, c);
5579 if (surface->lightmapinfo->styles[1] != 255)
5581 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5583 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5584 VectorMA(c, scale, lm, c);
5585 if (surface->lightmapinfo->styles[2] != 255)
5588 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5589 VectorMA(c, scale, lm, c);
5590 if (surface->lightmapinfo->styles[3] != 255)
5593 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5594 VectorMA(c, scale, lm, c);
5604 rsurface.lightmapcolor4f = rsurface.array_color4f;
5605 rsurface.lightmapcolor4f_bufferobject = 0;
5606 rsurface.lightmapcolor4f_bufferoffset = 0;
5610 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5611 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5612 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5614 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5615 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5616 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5617 GL_Color(r, g, b, a);
5618 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5621 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5623 int texturesurfaceindex;
5627 vec3_t ambientcolor;
5628 vec3_t diffusecolor;
5632 VectorCopy(rsurface.modellight_lightdir, lightdir);
5633 f = 0.5f * r_refdef.lightmapintensity;
5634 ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5635 ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5636 ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5637 diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5638 diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5639 diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5640 if (VectorLength2(diffusecolor) > 0)
5642 // generate color arrays for the surfaces in this list
5643 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5645 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5646 int numverts = surface->num_vertices;
5647 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5648 c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5649 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5650 // q3-style directional shading
5651 for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5653 if ((f = DotProduct(c2, lightdir)) > 0)
5654 VectorMA(ambientcolor, f, diffusecolor, c);
5656 VectorCopy(ambientcolor, c);
5665 rsurface.lightmapcolor4f = rsurface.array_color4f;
5666 rsurface.lightmapcolor4f_bufferobject = 0;
5667 rsurface.lightmapcolor4f_bufferoffset = 0;
5671 r = ambientcolor[0];
5672 g = ambientcolor[1];
5673 b = ambientcolor[2];
5674 rsurface.lightmapcolor4f = NULL;
5675 rsurface.lightmapcolor4f_bufferobject = 0;
5676 rsurface.lightmapcolor4f_bufferoffset = 0;
5678 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5679 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5680 R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5681 GL_Color(r, g, b, a);
5682 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5685 void RSurf_SetupDepthAndCulling(void)
5687 // submodels are biased to avoid z-fighting with world surfaces that they
5688 // may be exactly overlapping (avoids z-fighting artifacts on certain
5689 // doors and things in Quake maps)
5690 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5691 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5692 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5693 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5696 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5698 // transparent sky would be ridiculous
5699 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5701 R_SetupGenericShader(false);
5704 skyrendernow = false;
5705 // we have to force off the water clipping plane while rendering sky
5709 // restore entity matrix
5710 R_Mesh_Matrix(&rsurface.matrix);
5712 RSurf_SetupDepthAndCulling();
5714 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5715 // skymasking on them, and Quake3 never did sky masking (unlike
5716 // software Quake and software Quake2), so disable the sky masking
5717 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5718 // and skymasking also looks very bad when noclipping outside the
5719 // level, so don't use it then either.
5720 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5722 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5723 R_Mesh_ColorPointer(NULL, 0, 0);
5724 R_Mesh_ResetTextureState();
5725 if (skyrendermasked)
5727 R_SetupDepthOrShadowShader();
5728 // depth-only (masking)
5729 GL_ColorMask(0,0,0,0);
5730 // just to make sure that braindead drivers don't draw
5731 // anything despite that colormask...
5732 GL_BlendFunc(GL_ZERO, GL_ONE);
5736 R_SetupGenericShader(false);
5738 GL_BlendFunc(GL_ONE, GL_ZERO);
5740 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5741 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5742 if (skyrendermasked)
5743 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5745 R_Mesh_ResetTextureState();
5746 GL_Color(1, 1, 1, 1);
5749 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5751 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5754 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5755 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5756 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
5757 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
5758 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
5759 if (rsurface.texture->backgroundcurrentskinframe)
5761 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
5762 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
5763 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
5764 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
5766 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
5767 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5768 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
5769 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5770 R_Mesh_ColorPointer(NULL, 0, 0);
5772 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5774 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5776 // render background
5777 GL_BlendFunc(GL_ONE, GL_ZERO);
5779 GL_AlphaTest(false);
5781 GL_Color(1, 1, 1, 1);
5782 R_Mesh_ColorPointer(NULL, 0, 0);
5784 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5785 if (r_glsl_permutation)
5787 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5788 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5789 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5790 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5791 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5792 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5793 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);
5795 GL_LockArrays(0, 0);
5797 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5798 GL_DepthMask(false);
5799 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5800 R_Mesh_ColorPointer(NULL, 0, 0);
5802 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5803 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
5804 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
5807 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5808 if (!r_glsl_permutation)
5811 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5812 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5813 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5814 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5815 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5816 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5818 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5820 GL_BlendFunc(GL_ONE, GL_ZERO);
5822 GL_AlphaTest(false);
5826 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5827 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5828 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5831 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5833 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5834 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);
5836 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
5840 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5841 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);
5843 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5845 GL_LockArrays(0, 0);
5848 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5850 // OpenGL 1.3 path - anything not completely ancient
5851 int texturesurfaceindex;
5852 qboolean applycolor;
5856 const texturelayer_t *layer;
5857 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5859 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5862 int layertexrgbscale;
5863 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5865 if (layerindex == 0)
5869 GL_AlphaTest(false);
5870 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5873 GL_DepthMask(layer->depthmask && writedepth);
5874 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5875 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5877 layertexrgbscale = 4;
5878 VectorScale(layer->color, 0.25f, layercolor);
5880 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5882 layertexrgbscale = 2;
5883 VectorScale(layer->color, 0.5f, layercolor);
5887 layertexrgbscale = 1;
5888 VectorScale(layer->color, 1.0f, layercolor);
5890 layercolor[3] = layer->color[3];
5891 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5892 R_Mesh_ColorPointer(NULL, 0, 0);
5893 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5894 switch (layer->type)
5896 case TEXTURELAYERTYPE_LITTEXTURE:
5897 memset(&m, 0, sizeof(m));
5898 m.tex[0] = R_GetTexture(r_texture_white);
5899 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5900 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5901 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5902 m.tex[1] = R_GetTexture(layer->texture);
5903 m.texmatrix[1] = layer->texmatrix;
5904 m.texrgbscale[1] = layertexrgbscale;
5905 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5906 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5907 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5908 R_Mesh_TextureState(&m);
5909 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5910 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5911 else if (rsurface.uselightmaptexture)
5912 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5914 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5916 case TEXTURELAYERTYPE_TEXTURE:
5917 memset(&m, 0, sizeof(m));
5918 m.tex[0] = R_GetTexture(layer->texture);
5919 m.texmatrix[0] = layer->texmatrix;
5920 m.texrgbscale[0] = layertexrgbscale;
5921 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5922 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5923 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5924 R_Mesh_TextureState(&m);
5925 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5927 case TEXTURELAYERTYPE_FOG:
5928 memset(&m, 0, sizeof(m));
5929 m.texrgbscale[0] = layertexrgbscale;
5932 m.tex[0] = R_GetTexture(layer->texture);
5933 m.texmatrix[0] = layer->texmatrix;
5934 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5935 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5936 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5938 R_Mesh_TextureState(&m);
5939 // generate a color array for the fog pass
5940 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5941 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5945 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5946 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)
5948 f = 1 - FogPoint_Model(v);
5949 c[0] = layercolor[0];
5950 c[1] = layercolor[1];
5951 c[2] = layercolor[2];
5952 c[3] = f * layercolor[3];
5955 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5958 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5960 GL_LockArrays(0, 0);
5963 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5965 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5966 GL_AlphaTest(false);
5970 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5972 // OpenGL 1.1 - crusty old voodoo path
5973 int texturesurfaceindex;
5977 const texturelayer_t *layer;
5978 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5980 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5982 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5984 if (layerindex == 0)
5988 GL_AlphaTest(false);
5989 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5992 GL_DepthMask(layer->depthmask && writedepth);
5993 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5994 R_Mesh_ColorPointer(NULL, 0, 0);
5995 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5996 switch (layer->type)
5998 case TEXTURELAYERTYPE_LITTEXTURE:
5999 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6001 // two-pass lit texture with 2x rgbscale
6002 // first the lightmap pass
6003 memset(&m, 0, sizeof(m));
6004 m.tex[0] = R_GetTexture(r_texture_white);
6005 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6006 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6007 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6008 R_Mesh_TextureState(&m);
6009 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6010 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6011 else if (rsurface.uselightmaptexture)
6012 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6014 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6015 GL_LockArrays(0, 0);
6016 // then apply the texture to it
6017 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6018 memset(&m, 0, sizeof(m));
6019 m.tex[0] = R_GetTexture(layer->texture);
6020 m.texmatrix[0] = layer->texmatrix;
6021 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6022 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6023 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6024 R_Mesh_TextureState(&m);
6025 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);
6029 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6030 memset(&m, 0, sizeof(m));
6031 m.tex[0] = R_GetTexture(layer->texture);
6032 m.texmatrix[0] = layer->texmatrix;
6033 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6034 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6035 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6036 R_Mesh_TextureState(&m);
6037 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6038 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);
6040 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);
6043 case TEXTURELAYERTYPE_TEXTURE:
6044 // singletexture unlit texture with transparency support
6045 memset(&m, 0, sizeof(m));
6046 m.tex[0] = R_GetTexture(layer->texture);
6047 m.texmatrix[0] = layer->texmatrix;
6048 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6049 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6050 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6051 R_Mesh_TextureState(&m);
6052 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);
6054 case TEXTURELAYERTYPE_FOG:
6055 // singletexture fogging
6056 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6059 memset(&m, 0, sizeof(m));
6060 m.tex[0] = R_GetTexture(layer->texture);
6061 m.texmatrix[0] = layer->texmatrix;
6062 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6063 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6064 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6065 R_Mesh_TextureState(&m);
6068 R_Mesh_ResetTextureState();
6069 // generate a color array for the fog pass
6070 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6074 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6075 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)
6077 f = 1 - FogPoint_Model(v);
6078 c[0] = layer->color[0];
6079 c[1] = layer->color[1];
6080 c[2] = layer->color[2];
6081 c[3] = f * layer->color[3];
6084 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6087 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6089 GL_LockArrays(0, 0);
6092 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6094 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6095 GL_AlphaTest(false);
6099 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6102 RSurf_SetupDepthAndCulling();
6103 if (r_glsl.integer && gl_support_fragment_shader)
6104 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6105 else if (gl_combine.integer && r_textureunits.integer >= 2)
6106 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6108 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6112 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6115 int texturenumsurfaces, endsurface;
6117 msurface_t *surface;
6118 msurface_t *texturesurfacelist[1024];
6120 // if the model is static it doesn't matter what value we give for
6121 // wantnormals and wanttangents, so this logic uses only rules applicable
6122 // to a model, knowing that they are meaningless otherwise
6123 if (ent == r_refdef.scene.worldentity)
6124 RSurf_ActiveWorldEntity();
6125 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6126 RSurf_ActiveModelEntity(ent, false, false);
6128 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6130 for (i = 0;i < numsurfaces;i = j)
6133 surface = rsurface.modelsurfaces + surfacelist[i];
6134 texture = surface->texture;
6135 R_UpdateTextureInfo(ent, texture);
6136 rsurface.texture = texture->currentframe;
6137 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6138 // scan ahead until we find a different texture
6139 endsurface = min(i + 1024, numsurfaces);
6140 texturenumsurfaces = 0;
6141 texturesurfacelist[texturenumsurfaces++] = surface;
6142 for (;j < endsurface;j++)
6144 surface = rsurface.modelsurfaces + surfacelist[j];
6145 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6147 texturesurfacelist[texturenumsurfaces++] = surface;
6149 // render the range of surfaces
6150 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6152 GL_AlphaTest(false);
6155 static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6160 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6162 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6164 RSurf_SetupDepthAndCulling();
6165 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6166 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6168 else if (r_showsurfaces.integer)
6170 RSurf_SetupDepthAndCulling();
6172 GL_BlendFunc(GL_ONE, GL_ZERO);
6174 GL_AlphaTest(false);
6175 R_Mesh_ColorPointer(NULL, 0, 0);
6176 R_Mesh_ResetTextureState();
6177 R_SetupGenericShader(false);
6178 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6179 if (!r_refdef.view.showdebug)
6181 GL_Color(0, 0, 0, 1);
6182 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6185 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6187 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6188 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6189 else if (!rsurface.texture->currentnumlayers)
6191 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) && queueentity)
6193 // transparent surfaces get pushed off into the transparent queue
6194 int surfacelistindex;
6195 const msurface_t *surface;
6196 vec3_t tempcenter, center;
6197 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6199 surface = texturesurfacelist[surfacelistindex];
6200 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6201 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6202 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6203 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6204 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6209 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6210 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6215 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6219 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6222 for (i = 0;i < numsurfaces;i++)
6223 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6224 R_Water_AddWaterPlane(surfacelist[i]);
6227 // break the surface list down into batches by texture and use of lightmapping
6228 for (i = 0;i < numsurfaces;i = j)
6231 // texture is the base texture pointer, rsurface.texture is the
6232 // current frame/skin the texture is directing us to use (for example
6233 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6234 // use skin 1 instead)
6235 texture = surfacelist[i]->texture;
6236 rsurface.texture = texture->currentframe;
6237 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6238 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6240 // if this texture is not the kind we want, skip ahead to the next one
6241 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6245 // simply scan ahead until we find a different texture or lightmap state
6246 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6248 // render the range of surfaces
6249 R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6253 float locboxvertex3f[6*4*3] =
6255 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6256 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6257 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6258 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6259 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6260 1,0,0, 0,0,0, 0,1,0, 1,1,0
6263 int locboxelement3i[6*2*3] =
6273 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6276 cl_locnode_t *loc = (cl_locnode_t *)ent;
6278 float vertex3f[6*4*3];
6280 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6281 GL_DepthMask(false);
6282 GL_DepthRange(0, 1);
6283 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6285 GL_CullFace(GL_NONE);
6286 R_Mesh_Matrix(&identitymatrix);
6288 R_Mesh_VertexPointer(vertex3f, 0, 0);
6289 R_Mesh_ColorPointer(NULL, 0, 0);
6290 R_Mesh_ResetTextureState();
6291 R_SetupGenericShader(false);
6294 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6295 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6296 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6297 surfacelist[0] < 0 ? 0.5f : 0.125f);
6299 if (VectorCompare(loc->mins, loc->maxs))
6301 VectorSet(size, 2, 2, 2);
6302 VectorMA(loc->mins, -0.5f, size, mins);
6306 VectorCopy(loc->mins, mins);
6307 VectorSubtract(loc->maxs, loc->mins, size);
6310 for (i = 0;i < 6*4*3;)
6311 for (j = 0;j < 3;j++, i++)
6312 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6314 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6317 void R_DrawLocs(void)
6320 cl_locnode_t *loc, *nearestloc;
6322 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6323 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6325 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6326 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6330 void R_DrawDebugModel(entity_render_t *ent)
6332 int i, j, k, l, flagsmask;
6333 const int *elements;
6335 msurface_t *surface;
6336 model_t *model = ent->model;
6339 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6341 R_Mesh_ColorPointer(NULL, 0, 0);
6342 R_Mesh_ResetTextureState();
6343 R_SetupGenericShader(false);
6344 GL_DepthRange(0, 1);
6345 GL_DepthTest(!r_showdisabledepthtest.integer);
6346 GL_DepthMask(false);
6347 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6349 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6351 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6352 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6354 if (brush->colbrushf && brush->colbrushf->numtriangles)
6356 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6357 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);
6358 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6361 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6363 if (surface->num_collisiontriangles)
6365 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6366 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);
6367 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6372 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6374 if (r_showtris.integer || r_shownormals.integer)
6376 if (r_showdisabledepthtest.integer)
6378 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6379 GL_DepthMask(false);
6383 GL_BlendFunc(GL_ONE, GL_ZERO);
6386 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6388 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6390 rsurface.texture = surface->texture->currentframe;
6391 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6393 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6394 if (r_showtris.value > 0)
6396 if (!rsurface.texture->currentlayers->depthmask)
6397 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6398 else if (ent == r_refdef.scene.worldentity)
6399 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6401 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6402 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6405 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6407 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6408 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6409 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6410 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6415 if (r_shownormals.value > 0)
6418 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6420 VectorCopy(rsurface.vertex3f + l * 3, v);
6421 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6422 qglVertex3f(v[0], v[1], v[2]);
6423 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6424 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6425 qglVertex3f(v[0], v[1], v[2]);
6430 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6432 VectorCopy(rsurface.vertex3f + l * 3, v);
6433 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6434 qglVertex3f(v[0], v[1], v[2]);
6435 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6436 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6437 qglVertex3f(v[0], v[1], v[2]);
6442 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6444 VectorCopy(rsurface.vertex3f + l * 3, v);
6445 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6446 qglVertex3f(v[0], v[1], v[2]);
6447 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6448 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6449 qglVertex3f(v[0], v[1], v[2]);
6456 rsurface.texture = NULL;
6460 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6461 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6463 int i, j, endj, f, flagsmask;
6464 msurface_t *surface;
6466 model_t *model = r_refdef.scene.worldmodel;
6467 const int maxsurfacelist = 1024;
6468 int numsurfacelist = 0;
6469 msurface_t *surfacelist[1024];
6473 RSurf_ActiveWorldEntity();
6475 // update light styles on this submodel
6476 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6478 model_brush_lightstyleinfo_t *style;
6479 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6481 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6483 msurface_t *surfaces = model->data_surfaces;
6484 int *list = style->surfacelist;
6485 style->value = r_refdef.scene.lightstylevalue[style->style];
6486 for (j = 0;j < style->numsurfaces;j++)
6487 surfaces[list[j]].cached_dlight = true;
6492 R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6493 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6497 R_DrawDebugModel(r_refdef.scene.worldentity);
6503 rsurface.uselightmaptexture = false;
6504 rsurface.texture = NULL;
6505 rsurface.rtlight = NULL;
6507 j = model->firstmodelsurface;
6508 endj = j + model->nummodelsurfaces;
6511 // quickly skip over non-visible surfaces
6512 for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
6514 // quickly iterate over visible surfaces
6515 for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
6517 // process this surface
6518 surface = model->data_surfaces + j;
6519 // if this surface fits the criteria, add it to the list
6520 if (surface->num_triangles)
6522 // if lightmap parameters changed, rebuild lightmap texture
6523 if (surface->cached_dlight)
6524 R_BuildLightMap(r_refdef.scene.worldentity, surface);
6525 // add face to draw list
6526 surfacelist[numsurfacelist++] = surface;
6527 r_refdef.stats.world_triangles += surface->num_triangles;
6528 if (numsurfacelist >= maxsurfacelist)
6530 r_refdef.stats.world_surfaces += numsurfacelist;
6531 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6537 r_refdef.stats.world_surfaces += numsurfacelist;
6539 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6540 GL_AlphaTest(false);
6543 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6545 int i, j, f, flagsmask;
6546 msurface_t *surface, *endsurface;
6548 model_t *model = ent->model;
6549 const int maxsurfacelist = 1024;
6550 int numsurfacelist = 0;
6551 msurface_t *surfacelist[1024];
6555 // if the model is static it doesn't matter what value we give for
6556 // wantnormals and wanttangents, so this logic uses only rules applicable
6557 // to a model, knowing that they are meaningless otherwise
6558 if (ent == r_refdef.scene.worldentity)
6559 RSurf_ActiveWorldEntity();
6560 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6561 RSurf_ActiveModelEntity(ent, false, false);
6563 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6565 // update light styles
6566 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6568 model_brush_lightstyleinfo_t *style;
6569 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6571 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6573 msurface_t *surfaces = model->data_surfaces;
6574 int *list = style->surfacelist;
6575 style->value = r_refdef.scene.lightstylevalue[style->style];
6576 for (j = 0;j < style->numsurfaces;j++)
6577 surfaces[list[j]].cached_dlight = true;
6582 R_UpdateAllTextureInfo(ent);
6583 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6587 R_DrawDebugModel(ent);
6593 rsurface.uselightmaptexture = false;
6594 rsurface.texture = NULL;
6595 rsurface.rtlight = NULL;
6597 surface = model->data_surfaces + model->firstmodelsurface;
6598 endsurface = surface + model->nummodelsurfaces;
6599 for (;surface < endsurface;surface++)
6601 // if this surface fits the criteria, add it to the list
6602 if (surface->num_triangles)
6604 // if lightmap parameters changed, rebuild lightmap texture
6605 if (surface->cached_dlight)
6606 R_BuildLightMap(ent, surface);
6607 // add face to draw list
6608 surfacelist[numsurfacelist++] = surface;
6609 r_refdef.stats.entities_triangles += surface->num_triangles;
6610 if (numsurfacelist >= maxsurfacelist)
6612 r_refdef.stats.entities_surfaces += numsurfacelist;
6613 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6618 r_refdef.stats.entities_surfaces += numsurfacelist;
6620 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6621 GL_AlphaTest(false);