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_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
80 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
81 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
82 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
83 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
84 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
86 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)"};
87 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
88 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"};
89 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
90 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
92 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
93 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
94 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
95 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
97 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
98 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
99 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
100 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
101 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
102 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
103 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
105 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
106 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
107 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
108 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)"};
110 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"};
112 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"};
114 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
116 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
117 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
118 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"};
119 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
120 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
121 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
123 extern qboolean v_flipped_state;
125 typedef struct r_glsl_bloomshader_s
128 int loc_Texture_Bloom;
130 r_glsl_bloomshader_t;
132 static struct r_bloomstate_s
137 int bloomwidth, bloomheight;
139 int screentexturewidth, screentextureheight;
140 rtexture_t *texture_screen;
142 int bloomtexturewidth, bloomtextureheight;
143 rtexture_t *texture_bloom;
145 r_glsl_bloomshader_t *shader;
147 // arrays for rendering the screen passes
148 float screentexcoord2f[8];
149 float bloomtexcoord2f[8];
150 float offsettexcoord2f[8];
154 typedef struct r_waterstate_waterplane_s
156 rtexture_t *texture_refraction;
157 rtexture_t *texture_reflection;
159 int materialflags; // combined flags of all water surfaces on this plane
160 unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
163 r_waterstate_waterplane_t;
165 #define MAX_WATERPLANES 16
167 static struct r_waterstate_s
171 qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
173 int waterwidth, waterheight;
174 int texturewidth, textureheight;
176 int maxwaterplanes; // same as MAX_WATERPLANES
178 r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
180 float screenscale[2];
181 float screencenter[2];
185 // shadow volume bsp struct with automatically growing nodes buffer
188 rtexture_t *r_texture_blanknormalmap;
189 rtexture_t *r_texture_white;
190 rtexture_t *r_texture_grey128;
191 rtexture_t *r_texture_black;
192 rtexture_t *r_texture_notexture;
193 rtexture_t *r_texture_whitecube;
194 rtexture_t *r_texture_normalizationcube;
195 rtexture_t *r_texture_fogattenuation;
196 //rtexture_t *r_texture_fogintensity;
198 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
199 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
201 // vertex coordinates for a quad that covers the screen exactly
202 const static float r_screenvertex3f[12] =
210 extern void R_DrawModelShadows(void);
212 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
215 for (i = 0;i < verts;i++)
226 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
229 for (i = 0;i < verts;i++)
239 // FIXME: move this to client?
242 if (gamemode == GAME_NEHAHRA)
244 Cvar_Set("gl_fogenable", "0");
245 Cvar_Set("gl_fogdensity", "0.2");
246 Cvar_Set("gl_fogred", "0.3");
247 Cvar_Set("gl_foggreen", "0.3");
248 Cvar_Set("gl_fogblue", "0.3");
250 r_refdef.fog_density = 0;
251 r_refdef.fog_red = 0;
252 r_refdef.fog_green = 0;
253 r_refdef.fog_blue = 0;
254 r_refdef.fog_alpha = 1;
255 r_refdef.fog_start = 0;
256 r_refdef.fog_end = 0;
259 float FogForDistance(vec_t dist)
261 unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
262 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
265 float FogPoint_World(const vec3_t p)
267 return FogForDistance(VectorDistance((p), r_refdef.view.origin));
270 float FogPoint_Model(const vec3_t p)
272 return FogForDistance(VectorDistance((p), rsurface.modelorg));
275 static void R_BuildBlankTextures(void)
277 unsigned char data[4];
278 data[2] = 128; // normal X
279 data[1] = 128; // normal Y
280 data[0] = 255; // normal Z
281 data[3] = 128; // height
282 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
287 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
292 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
297 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
300 static void R_BuildNoTexture(void)
303 unsigned char pix[16][16][4];
304 // this makes a light grey/dark grey checkerboard texture
305 for (y = 0;y < 16;y++)
307 for (x = 0;x < 16;x++)
309 if ((y < 8) ^ (x < 8))
325 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
328 static void R_BuildWhiteCube(void)
330 unsigned char data[6*1*1*4];
331 memset(data, 255, sizeof(data));
332 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
335 static void R_BuildNormalizationCube(void)
339 vec_t s, t, intensity;
341 unsigned char data[6][NORMSIZE][NORMSIZE][4];
342 for (side = 0;side < 6;side++)
344 for (y = 0;y < NORMSIZE;y++)
346 for (x = 0;x < NORMSIZE;x++)
348 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
349 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
384 intensity = 127.0f / sqrt(DotProduct(v, v));
385 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
386 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
387 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
388 data[side][y][x][3] = 255;
392 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
395 static void R_BuildFogTexture(void)
399 unsigned char data1[FOGWIDTH][4];
400 //unsigned char data2[FOGWIDTH][4];
403 r_refdef.fogmasktable_start = r_refdef.fog_start;
404 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
405 r_refdef.fogmasktable_range = r_refdef.fogrange;
406 r_refdef.fogmasktable_density = r_refdef.fog_density;
408 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
409 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
411 d = (x * r - r_refdef.fogmasktable_start);
412 if(developer.integer >= 100)
413 Con_Printf("%f ", d);
415 if (r_fog_exp2.integer)
416 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
418 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
419 if(developer.integer >= 100)
420 Con_Printf(" : %f ", alpha);
421 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
422 if(developer.integer >= 100)
423 Con_Printf(" = %f\n", alpha);
424 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
427 for (x = 0;x < FOGWIDTH;x++)
429 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
434 //data2[x][0] = 255 - b;
435 //data2[x][1] = 255 - b;
436 //data2[x][2] = 255 - b;
439 if (r_texture_fogattenuation)
441 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
442 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
446 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);
447 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
451 static const char *builtinshaderstring =
452 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
453 "// written by Forest 'LordHavoc' Hale\n"
455 "// common definitions between vertex shader and fragment shader:\n"
457 "//#ifdef __GLSL_CG_DATA_TYPES\n"
458 "//# define myhalf half\n"
459 "//# define myhalf2 half2\n"
460 "//# define myhalf3 half3\n"
461 "//# define myhalf4 half4\n"
463 "# define myhalf float\n"
464 "# define myhalf2 vec2\n"
465 "# define myhalf3 vec3\n"
466 "# define myhalf4 vec4\n"
469 "#ifdef MODE_DEPTH_OR_SHADOW\n"
471 "# ifdef VERTEX_SHADER\n"
474 " gl_Position = ftransform();\n"
479 "#ifdef MODE_GENERIC\n"
481 "# ifdef VERTEX_SHADER\n"
484 " gl_FrontColor = gl_Color;\n"
485 "# ifdef USEDIFFUSE\n"
486 " gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
488 "# ifdef USESPECULAR\n"
489 " gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
491 " gl_Position = ftransform();\n"
494 "# ifdef FRAGMENT_SHADER\n"
496 "# ifdef USEDIFFUSE\n"
497 "uniform sampler2D Texture_First;\n"
499 "# ifdef USESPECULAR\n"
500 "uniform sampler2D Texture_Second;\n"
505 " gl_FragColor = gl_Color;\n"
506 "# ifdef USEDIFFUSE\n"
507 " gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
510 "# ifdef USESPECULAR\n"
511 " vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
513 "# ifdef USECOLORMAPPING\n"
514 " gl_FragColor *= tex2;\n"
517 " gl_FragColor += tex2;\n"
519 "# ifdef USEVERTEXTEXTUREBLEND\n"
520 " gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n"
525 "#else // !MODE_GENERIC\n"
527 "varying vec2 TexCoord;\n"
528 "varying vec2 TexCoordLightmap;\n"
530 "//#ifdef MODE_LIGHTSOURCE\n"
531 "varying vec3 CubeVector;\n"
534 "//#ifdef MODE_LIGHTSOURCE\n"
535 "varying vec3 LightVector;\n"
537 "//# ifdef MODE_LIGHTDIRECTION\n"
538 "//varying vec3 LightVector;\n"
542 "varying vec3 EyeVector;\n"
544 "varying vec3 EyeVectorModelSpace;\n"
547 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
548 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
549 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
551 "//#ifdef MODE_WATER\n"
552 "varying vec4 ModelViewProjectionPosition;\n"
554 "//# ifdef MODE_REFRACTION\n"
555 "//varying vec4 ModelViewProjectionPosition;\n"
557 "//# ifdef USEREFLECTION\n"
558 "//varying vec4 ModelViewProjectionPosition;\n"
567 "// vertex shader specific:\n"
568 "#ifdef VERTEX_SHADER\n"
570 "uniform vec3 LightPosition;\n"
571 "uniform vec3 EyePosition;\n"
572 "uniform vec3 LightDir;\n"
574 "// 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"
578 " gl_FrontColor = gl_Color;\n"
579 " // copy the surface texcoord\n"
580 " TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
581 "#ifndef MODE_LIGHTSOURCE\n"
582 "# ifndef MODE_LIGHTDIRECTION\n"
583 " TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
587 "#ifdef MODE_LIGHTSOURCE\n"
588 " // transform vertex position into light attenuation/cubemap space\n"
589 " // (-1 to +1 across the light box)\n"
590 " CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
592 " // transform unnormalized light direction into tangent space\n"
593 " // (we use unnormalized to ensure that it interpolates correctly and then\n"
594 " // normalize it per pixel)\n"
595 " vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
596 " LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
597 " LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
598 " LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
601 "#ifdef MODE_LIGHTDIRECTION\n"
602 " LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
603 " LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
604 " LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
607 " // transform unnormalized eye direction into tangent space\n"
609 " vec3 EyeVectorModelSpace;\n"
611 " EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
612 " EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
613 " EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
614 " EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
616 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
617 " VectorS = gl_MultiTexCoord1.xyz;\n"
618 " VectorT = gl_MultiTexCoord2.xyz;\n"
619 " VectorR = gl_MultiTexCoord3.xyz;\n"
622 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
623 "// ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
624 "// //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
625 "// //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
628 "// transform vertex to camera space, using ftransform to match non-VS\n"
630 " gl_Position = ftransform();\n"
632 "#ifdef MODE_WATER\n"
633 " ModelViewProjectionPosition = gl_Position;\n"
635 "#ifdef MODE_REFRACTION\n"
636 " ModelViewProjectionPosition = gl_Position;\n"
638 "#ifdef USEREFLECTION\n"
639 " ModelViewProjectionPosition = gl_Position;\n"
643 "#endif // VERTEX_SHADER\n"
648 "// fragment shader specific:\n"
649 "#ifdef FRAGMENT_SHADER\n"
651 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
652 "uniform sampler2D Texture_Normal;\n"
653 "uniform sampler2D Texture_Color;\n"
654 "uniform sampler2D Texture_Gloss;\n"
655 "uniform sampler2D Texture_Glow;\n"
656 "uniform sampler2D Texture_SecondaryNormal;\n"
657 "uniform sampler2D Texture_SecondaryColor;\n"
658 "uniform sampler2D Texture_SecondaryGloss;\n"
659 "uniform sampler2D Texture_SecondaryGlow;\n"
660 "uniform sampler2D Texture_Pants;\n"
661 "uniform sampler2D Texture_Shirt;\n"
662 "uniform sampler2D Texture_FogMask;\n"
663 "uniform sampler2D Texture_Lightmap;\n"
664 "uniform sampler2D Texture_Deluxemap;\n"
665 "uniform sampler2D Texture_Refraction;\n"
666 "uniform sampler2D Texture_Reflection;\n"
667 "uniform sampler2D Texture_Attenuation;\n"
668 "uniform samplerCube Texture_Cube;\n"
670 "uniform myhalf3 LightColor;\n"
671 "uniform myhalf3 AmbientColor;\n"
672 "uniform myhalf3 DiffuseColor;\n"
673 "uniform myhalf3 SpecularColor;\n"
674 "uniform myhalf3 Color_Pants;\n"
675 "uniform myhalf3 Color_Shirt;\n"
676 "uniform myhalf3 FogColor;\n"
678 "uniform myhalf4 TintColor;\n"
681 "//#ifdef MODE_WATER\n"
682 "uniform vec4 DistortScaleRefractReflect;\n"
683 "uniform vec4 ScreenScaleRefractReflect;\n"
684 "uniform vec4 ScreenCenterRefractReflect;\n"
685 "uniform myhalf4 RefractColor;\n"
686 "uniform myhalf4 ReflectColor;\n"
687 "uniform myhalf ReflectFactor;\n"
688 "uniform myhalf ReflectOffset;\n"
690 "//# ifdef MODE_REFRACTION\n"
691 "//uniform vec4 DistortScaleRefractReflect;\n"
692 "//uniform vec4 ScreenScaleRefractReflect;\n"
693 "//uniform vec4 ScreenCenterRefractReflect;\n"
694 "//uniform myhalf4 RefractColor;\n"
695 "//# ifdef USEREFLECTION\n"
696 "//uniform myhalf4 ReflectColor;\n"
699 "//# ifdef USEREFLECTION\n"
700 "//uniform vec4 DistortScaleRefractReflect;\n"
701 "//uniform vec4 ScreenScaleRefractReflect;\n"
702 "//uniform vec4 ScreenCenterRefractReflect;\n"
703 "//uniform myhalf4 ReflectColor;\n"
708 "uniform myhalf GlowScale;\n"
709 "uniform myhalf SceneBrightness;\n"
710 "#ifdef USECONTRASTBOOST\n"
711 "uniform myhalf ContrastBoostCoeff;\n"
714 "uniform float OffsetMapping_Scale;\n"
715 "uniform float OffsetMapping_Bias;\n"
716 "uniform float FogRangeRecip;\n"
718 "uniform myhalf AmbientScale;\n"
719 "uniform myhalf DiffuseScale;\n"
720 "uniform myhalf SpecularScale;\n"
721 "uniform myhalf SpecularPower;\n"
723 "#ifdef USEOFFSETMAPPING\n"
724 "vec2 OffsetMapping(vec2 TexCoord)\n"
726 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
727 " // 14 sample relief mapping: linear search and then binary search\n"
728 " // this basically steps forward a small amount repeatedly until it finds\n"
729 " // itself inside solid, then jitters forward and back using decreasing\n"
730 " // amounts to find the impact\n"
731 " //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
732 " //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
733 " vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
734 " vec3 RT = vec3(TexCoord, 1);\n"
735 " OffsetVector *= 0.1;\n"
736 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
737 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
738 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
739 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
740 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
741 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
742 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
743 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
744 " RT += OffsetVector * step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
745 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) - 0.5);\n"
746 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5 - 0.25);\n"
747 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25 - 0.125);\n"
748 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125 - 0.0625);\n"
749 " RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
752 " // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
753 " // this basically moves forward the full distance, and then backs up based\n"
754 " // on height of samples\n"
755 " //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
756 " //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
757 " vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
758 " TexCoord += OffsetVector;\n"
759 " OffsetVector *= 0.333;\n"
760 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
761 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
762 " TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
763 " return TexCoord;\n"
766 "#endif // USEOFFSETMAPPING\n"
768 "#ifdef MODE_WATER\n"
773 "#ifdef USEOFFSETMAPPING\n"
774 " // apply offsetmapping\n"
775 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
776 "#define TexCoord TexCoordOffset\n"
779 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
780 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
781 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
782 " float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
783 " gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
786 "#else // !MODE_WATER\n"
787 "#ifdef MODE_REFRACTION\n"
789 "// refraction pass\n"
792 "#ifdef USEOFFSETMAPPING\n"
793 " // apply offsetmapping\n"
794 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
795 "#define TexCoord TexCoordOffset\n"
798 " vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
799 " //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
800 " vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
801 " gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
804 "#else // !MODE_REFRACTION\n"
807 "#ifdef USEOFFSETMAPPING\n"
808 " // apply offsetmapping\n"
809 " vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
810 "#define TexCoord TexCoordOffset\n"
813 " // combine the diffuse textures (base, pants, shirt)\n"
814 " myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
815 "#ifdef USECOLORMAPPING\n"
816 " color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
818 "#ifdef USEVERTEXTEXTUREBLEND\n"
819 " myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
820 " //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
821 " //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
822 " color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n"
823 " //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
826 "#ifdef USEDIFFUSE\n"
827 " // get the surface normal and the gloss color\n"
828 "# ifdef USEVERTEXTEXTUREBLEND\n"
829 " myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
830 "# ifdef USESPECULAR\n"
831 " myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
834 " myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
835 "# ifdef USESPECULAR\n"
836 " myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
843 "#ifdef MODE_LIGHTSOURCE\n"
846 " // calculate surface normal, light normal, and specular normal\n"
847 " // compute color intensity for the two textures (colormap and glossmap)\n"
848 " // scale by light color and attenuation as efficiently as possible\n"
849 " // (do as much scalar math as possible rather than vector math)\n"
850 "# ifdef USEDIFFUSE\n"
851 " // get the light normal\n"
852 " myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
854 "# ifdef USESPECULAR\n"
855 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
857 " // calculate directional shading\n"
858 " 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"
860 "# ifdef USEDIFFUSE\n"
861 " // calculate directional shading\n"
862 " color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
864 " // calculate directionless shading\n"
865 " color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
869 "# ifdef USECUBEFILTER\n"
870 " // apply light cubemap filter\n"
871 " //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
872 " color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
874 "#endif // MODE_LIGHTSOURCE\n"
879 "#ifdef MODE_LIGHTDIRECTION\n"
880 " // directional model lighting\n"
881 "# ifdef USEDIFFUSE\n"
882 " // get the light normal\n"
883 " myhalf3 diffusenormal = myhalf3(LightVector);\n"
885 "# ifdef USESPECULAR\n"
886 " // calculate directional shading\n"
887 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
888 " myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
889 " color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
891 "# ifdef USEDIFFUSE\n"
893 " // calculate directional shading\n"
894 " color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
896 " color.rgb *= AmbientColor;\n"
899 "#endif // MODE_LIGHTDIRECTION\n"
904 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
905 " // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
907 " // get the light normal\n"
908 " myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n"
909 " myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n"
910 " // calculate directional shading\n"
911 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
912 "# ifdef USESPECULAR\n"
913 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
914 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
917 " // apply lightmap color\n"
918 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
919 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
924 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
925 " // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
927 " // get the light normal\n"
928 " myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
929 " // calculate directional shading\n"
930 " myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
931 "# ifdef USESPECULAR\n"
932 " myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
933 " tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
936 " // apply lightmap color\n"
937 " color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
938 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
943 "#ifdef MODE_LIGHTMAP\n"
944 " // apply lightmap color\n"
945 " color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
946 "#endif // MODE_LIGHTMAP\n"
951 "#ifdef MODE_VERTEXCOLOR\n"
952 " // apply lightmap color\n"
953 " color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
954 "#endif // MODE_VERTEXCOLOR\n"
959 "#ifdef MODE_FLATCOLOR\n"
960 "#endif // MODE_FLATCOLOR\n"
968 " color *= TintColor;\n"
971 " color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
974 "#ifdef USECONTRASTBOOST\n"
975 " color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
978 " color.rgb *= SceneBrightness;\n"
980 " // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
982 " color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
985 " // 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"
986 "#ifdef USEREFLECTION\n"
987 " vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
988 " //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
989 " vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
990 " color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
993 " gl_FragColor = vec4(color);\n"
995 "#endif // !MODE_REFRACTION\n"
996 "#endif // !MODE_WATER\n"
998 "#endif // FRAGMENT_SHADER\n"
1000 "#endif // !MODE_GENERIC\n"
1001 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1004 typedef struct shaderpermutationinfo_s
1006 const char *pretext;
1009 shaderpermutationinfo_t;
1011 typedef struct shadermodeinfo_s
1013 const char *vertexfilename;
1014 const char *geometryfilename;
1015 const char *fragmentfilename;
1016 const char *pretext;
1021 typedef enum shaderpermutation_e
1023 SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1024 SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1025 SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1026 SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1027 SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1028 SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1029 SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1030 SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1031 SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1032 SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface
1033 SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1034 SHADERPERMUTATION_LIMIT = 1<<11, // size of permutations array
1035 SHADERPERMUTATION_COUNT = 11 // size of shaderpermutationinfo array
1037 shaderpermutation_t;
1039 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1040 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1042 {"#define USEDIFFUSE\n", " diffuse"},
1043 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1044 {"#define USECOLORMAPPING\n", " colormapping"},
1045 {"#define USECONTRASTBOOST\n", " contrastboost"},
1046 {"#define USEFOG\n", " fog"},
1047 {"#define USECUBEFILTER\n", " cubefilter"},
1048 {"#define USEGLOW\n", " glow"},
1049 {"#define USESPECULAR\n", " specular"},
1050 {"#define USEREFLECTION\n", " reflection"},
1051 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1052 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1055 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1056 typedef enum shadermode_e
1058 SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1059 SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1060 SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1061 SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1062 SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1063 SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1064 SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1065 SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1066 SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1067 SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1068 SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1073 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1074 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1076 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1077 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1078 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1079 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1080 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1081 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1082 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1083 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1084 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1085 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1086 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1089 typedef struct r_glsl_permutation_s
1091 // indicates if we have tried compiling this permutation already
1093 // 0 if compilation failed
1095 // locations of detected uniforms in program object, or -1 if not found
1096 int loc_Texture_First;
1097 int loc_Texture_Second;
1098 int loc_Texture_Normal;
1099 int loc_Texture_Color;
1100 int loc_Texture_Gloss;
1101 int loc_Texture_Glow;
1102 int loc_Texture_SecondaryNormal;
1103 int loc_Texture_SecondaryColor;
1104 int loc_Texture_SecondaryGloss;
1105 int loc_Texture_SecondaryGlow;
1106 int loc_Texture_Pants;
1107 int loc_Texture_Shirt;
1108 int loc_Texture_FogMask;
1109 int loc_Texture_Lightmap;
1110 int loc_Texture_Deluxemap;
1111 int loc_Texture_Attenuation;
1112 int loc_Texture_Cube;
1113 int loc_Texture_Refraction;
1114 int loc_Texture_Reflection;
1116 int loc_LightPosition;
1117 int loc_EyePosition;
1118 int loc_Color_Pants;
1119 int loc_Color_Shirt;
1120 int loc_FogRangeRecip;
1121 int loc_AmbientScale;
1122 int loc_DiffuseScale;
1123 int loc_SpecularScale;
1124 int loc_SpecularPower;
1126 int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1127 int loc_OffsetMapping_Scale;
1129 int loc_AmbientColor;
1130 int loc_DiffuseColor;
1131 int loc_SpecularColor;
1133 int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1134 int loc_DistortScaleRefractReflect;
1135 int loc_ScreenScaleRefractReflect;
1136 int loc_ScreenCenterRefractReflect;
1137 int loc_RefractColor;
1138 int loc_ReflectColor;
1139 int loc_ReflectFactor;
1140 int loc_ReflectOffset;
1142 r_glsl_permutation_t;
1144 // information about each possible shader permutation
1145 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1146 // currently selected permutation
1147 r_glsl_permutation_t *r_glsl_permutation;
1149 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1152 if (!filename || !filename[0])
1154 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1157 if (printfromdisknotice)
1158 Con_DPrint("from disk... ");
1159 return shaderstring;
1161 else if (!strcmp(filename, "glsl/default.glsl"))
1163 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1164 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1166 return shaderstring;
1169 static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t permutation)
1172 shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1173 r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1174 int vertstrings_count = 0;
1175 int geomstrings_count = 0;
1176 int fragstrings_count = 0;
1177 char *vertexstring, *geometrystring, *fragmentstring;
1178 const char *vertstrings_list[32+3];
1179 const char *geomstrings_list[32+3];
1180 const char *fragstrings_list[32+3];
1181 char permutationname[256];
1188 permutationname[0] = 0;
1189 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1190 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1191 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1193 strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1195 // the first pretext is which type of shader to compile as
1196 // (later these will all be bound together as a program object)
1197 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1198 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1199 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1201 // the second pretext is the mode (for example a light source)
1202 vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1203 geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1204 fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1205 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1207 // now add all the permutation pretexts
1208 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1210 if (permutation & (1<<i))
1212 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1213 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1214 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1215 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1219 // keep line numbers correct
1220 vertstrings_list[vertstrings_count++] = "\n";
1221 geomstrings_list[geomstrings_count++] = "\n";
1222 fragstrings_list[fragstrings_count++] = "\n";
1226 // now append the shader text itself
1227 vertstrings_list[vertstrings_count++] = vertexstring;
1228 geomstrings_list[geomstrings_count++] = geometrystring;
1229 fragstrings_list[fragstrings_count++] = fragmentstring;
1231 // if any sources were NULL, clear the respective list
1233 vertstrings_count = 0;
1234 if (!geometrystring)
1235 geomstrings_count = 0;
1236 if (!fragmentstring)
1237 fragstrings_count = 0;
1239 // compile the shader program
1240 if (vertstrings_count + geomstrings_count + fragstrings_count)
1241 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1245 qglUseProgramObjectARB(p->program);CHECKGLERROR
1246 // look up all the uniform variable names we care about, so we don't
1247 // have to look them up every time we set them
1248 p->loc_Texture_First = qglGetUniformLocationARB(p->program, "Texture_First");
1249 p->loc_Texture_Second = qglGetUniformLocationARB(p->program, "Texture_Second");
1250 p->loc_Texture_Normal = qglGetUniformLocationARB(p->program, "Texture_Normal");
1251 p->loc_Texture_Color = qglGetUniformLocationARB(p->program, "Texture_Color");
1252 p->loc_Texture_Gloss = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1253 p->loc_Texture_Glow = qglGetUniformLocationARB(p->program, "Texture_Glow");
1254 p->loc_Texture_SecondaryNormal = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1255 p->loc_Texture_SecondaryColor = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1256 p->loc_Texture_SecondaryGloss = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1257 p->loc_Texture_SecondaryGlow = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1258 p->loc_Texture_FogMask = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1259 p->loc_Texture_Pants = qglGetUniformLocationARB(p->program, "Texture_Pants");
1260 p->loc_Texture_Shirt = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1261 p->loc_Texture_Lightmap = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1262 p->loc_Texture_Deluxemap = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1263 p->loc_Texture_Refraction = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1264 p->loc_Texture_Reflection = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1265 p->loc_Texture_Attenuation = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1266 p->loc_Texture_Cube = qglGetUniformLocationARB(p->program, "Texture_Cube");
1267 p->loc_FogColor = qglGetUniformLocationARB(p->program, "FogColor");
1268 p->loc_LightPosition = qglGetUniformLocationARB(p->program, "LightPosition");
1269 p->loc_EyePosition = qglGetUniformLocationARB(p->program, "EyePosition");
1270 p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants");
1271 p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt");
1272 p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1273 p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale");
1274 p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale");
1275 p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower");
1276 p->loc_SpecularScale = qglGetUniformLocationARB(p->program, "SpecularScale");
1277 p->loc_GlowScale = qglGetUniformLocationARB(p->program, "GlowScale");
1278 p->loc_SceneBrightness = qglGetUniformLocationARB(p->program, "SceneBrightness");
1279 p->loc_OffsetMapping_Scale = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1280 p->loc_TintColor = qglGetUniformLocationARB(p->program, "TintColor");
1281 p->loc_AmbientColor = qglGetUniformLocationARB(p->program, "AmbientColor");
1282 p->loc_DiffuseColor = qglGetUniformLocationARB(p->program, "DiffuseColor");
1283 p->loc_SpecularColor = qglGetUniformLocationARB(p->program, "SpecularColor");
1284 p->loc_LightDir = qglGetUniformLocationARB(p->program, "LightDir");
1285 p->loc_ContrastBoostCoeff = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1286 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1287 p->loc_ScreenScaleRefractReflect = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1288 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1289 p->loc_RefractColor = qglGetUniformLocationARB(p->program, "RefractColor");
1290 p->loc_ReflectColor = qglGetUniformLocationARB(p->program, "ReflectColor");
1291 p->loc_ReflectFactor = qglGetUniformLocationARB(p->program, "ReflectFactor");
1292 p->loc_ReflectOffset = qglGetUniformLocationARB(p->program, "ReflectOffset");
1293 // initialize the samplers to refer to the texture units we use
1294 if (p->loc_Texture_First >= 0) qglUniform1iARB(p->loc_Texture_First , GL20TU_FIRST);
1295 if (p->loc_Texture_Second >= 0) qglUniform1iARB(p->loc_Texture_Second , GL20TU_SECOND);
1296 if (p->loc_Texture_Normal >= 0) qglUniform1iARB(p->loc_Texture_Normal , GL20TU_NORMAL);
1297 if (p->loc_Texture_Color >= 0) qglUniform1iARB(p->loc_Texture_Color , GL20TU_COLOR);
1298 if (p->loc_Texture_Gloss >= 0) qglUniform1iARB(p->loc_Texture_Gloss , GL20TU_GLOSS);
1299 if (p->loc_Texture_Glow >= 0) qglUniform1iARB(p->loc_Texture_Glow , GL20TU_GLOW);
1300 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1301 if (p->loc_Texture_SecondaryColor >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1302 if (p->loc_Texture_SecondaryGloss >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1303 if (p->loc_Texture_SecondaryGlow >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow , GL20TU_SECONDARY_GLOW);
1304 if (p->loc_Texture_Pants >= 0) qglUniform1iARB(p->loc_Texture_Pants , GL20TU_PANTS);
1305 if (p->loc_Texture_Shirt >= 0) qglUniform1iARB(p->loc_Texture_Shirt , GL20TU_SHIRT);
1306 if (p->loc_Texture_FogMask >= 0) qglUniform1iARB(p->loc_Texture_FogMask , GL20TU_FOGMASK);
1307 if (p->loc_Texture_Lightmap >= 0) qglUniform1iARB(p->loc_Texture_Lightmap , GL20TU_LIGHTMAP);
1308 if (p->loc_Texture_Deluxemap >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap , GL20TU_DELUXEMAP);
1309 if (p->loc_Texture_Attenuation >= 0) qglUniform1iARB(p->loc_Texture_Attenuation , GL20TU_ATTENUATION);
1310 if (p->loc_Texture_Cube >= 0) qglUniform1iARB(p->loc_Texture_Cube , GL20TU_CUBE);
1311 if (p->loc_Texture_Refraction >= 0) qglUniform1iARB(p->loc_Texture_Refraction , GL20TU_REFRACTION);
1312 if (p->loc_Texture_Reflection >= 0) qglUniform1iARB(p->loc_Texture_Reflection , GL20TU_REFLECTION);
1314 if (developer.integer)
1315 Con_Printf("GLSL shader %s compiled.\n", permutationname);
1318 Con_Printf("GLSL shader %s failed! some features may not work properly.\n", permutationname);
1322 Mem_Free(vertexstring);
1324 Mem_Free(geometrystring);
1326 Mem_Free(fragmentstring);
1329 void R_GLSL_Restart_f(void)
1332 shaderpermutation_t permutation;
1333 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1334 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1335 if (r_glsl_permutations[mode][permutation].program)
1336 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1337 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1340 void R_GLSL_DumpShader_f(void)
1344 qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1347 Con_Printf("failed to write to glsl/default.glsl\n");
1351 FS_Print(file, "// The engine may define the following macros:\n");
1352 FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1353 for (i = 0;i < SHADERMODE_COUNT;i++)
1354 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1355 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1356 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1357 FS_Print(file, "\n");
1358 FS_Print(file, builtinshaderstring);
1361 Con_Printf("glsl/default.glsl written\n");
1364 void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation)
1366 r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1367 if (r_glsl_permutation != perm)
1369 r_glsl_permutation = perm;
1370 if (!r_glsl_permutation->program)
1372 if (!r_glsl_permutation->compiled)
1373 R_GLSL_CompilePermutation(mode, permutation);
1374 if (!r_glsl_permutation->program)
1376 // remove features until we find a valid permutation
1378 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1380 // reduce i more quickly whenever it would not remove any bits
1381 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1382 if (!(permutation & j))
1385 r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1386 if (!r_glsl_permutation->compiled)
1387 R_GLSL_CompilePermutation(mode, permutation);
1388 if (r_glsl_permutation->program)
1391 if (i >= SHADERPERMUTATION_COUNT)
1393 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");
1394 Cvar_SetValueQuick(&r_glsl, 0);
1395 R_GLSL_Restart_f(); // unload shaders
1396 return; // no bit left to clear
1401 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1405 void R_SetupGenericShader(qboolean usetexture)
1407 if (gl_support_fragment_shader)
1409 if (r_glsl.integer && r_glsl_usegeneric.integer)
1410 R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1411 else if (r_glsl_permutation)
1413 r_glsl_permutation = NULL;
1414 qglUseProgramObjectARB(0);CHECKGLERROR
1419 void R_SetupGenericTwoTextureShader(int texturemode)
1421 if (gl_support_fragment_shader)
1423 if (r_glsl.integer && r_glsl_usegeneric.integer)
1424 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))));
1425 else if (r_glsl_permutation)
1427 r_glsl_permutation = NULL;
1428 qglUseProgramObjectARB(0);CHECKGLERROR
1431 if (!r_glsl_permutation)
1433 if (texturemode == GL_DECAL && gl_combine.integer)
1434 texturemode = GL_INTERPOLATE_ARB;
1435 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1439 void R_SetupDepthOrShadowShader(void)
1441 if (gl_support_fragment_shader)
1443 if (r_glsl.integer && r_glsl_usegeneric.integer)
1444 R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1445 else if (r_glsl_permutation)
1447 r_glsl_permutation = NULL;
1448 qglUseProgramObjectARB(0);CHECKGLERROR
1453 extern rtexture_t *r_shadow_attenuationgradienttexture;
1454 extern rtexture_t *r_shadow_attenuation2dtexture;
1455 extern rtexture_t *r_shadow_attenuation3dtexture;
1456 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1458 // select a permutation of the lighting shader appropriate to this
1459 // combination of texture, entity, light source, and fogging, only use the
1460 // minimum features necessary to avoid wasting rendering time in the
1461 // fragment shader on features that are not being used
1462 unsigned int permutation = 0;
1463 shadermode_t mode = 0;
1464 // TODO: implement geometry-shader based shadow volumes someday
1465 if (r_glsl_offsetmapping.integer)
1467 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1468 if (r_glsl_offsetmapping_reliefmapping.integer)
1469 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1471 if (rsurfacepass == RSURFPASS_BACKGROUND)
1473 // distorted background
1474 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1475 mode = SHADERMODE_WATER;
1477 mode = SHADERMODE_REFRACTION;
1479 else if (rsurfacepass == RSURFPASS_RTLIGHT)
1482 mode = SHADERMODE_LIGHTSOURCE;
1483 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1484 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1485 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1486 permutation |= SHADERPERMUTATION_CUBEFILTER;
1487 if (diffusescale > 0)
1488 permutation |= SHADERPERMUTATION_DIFFUSE;
1489 if (specularscale > 0)
1490 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1491 if (r_refdef.fogenabled)
1492 permutation |= SHADERPERMUTATION_FOG;
1493 if (rsurface.texture->colormapping)
1494 permutation |= SHADERPERMUTATION_COLORMAPPING;
1495 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1496 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1498 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1500 // unshaded geometry (fullbright or ambient model lighting)
1501 mode = SHADERMODE_FLATCOLOR;
1502 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1503 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1504 if (rsurface.texture->currentskinframe->glow)
1505 permutation |= SHADERPERMUTATION_GLOW;
1506 if (r_refdef.fogenabled)
1507 permutation |= SHADERPERMUTATION_FOG;
1508 if (rsurface.texture->colormapping)
1509 permutation |= SHADERPERMUTATION_COLORMAPPING;
1510 if (r_glsl_offsetmapping.integer)
1512 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1513 if (r_glsl_offsetmapping_reliefmapping.integer)
1514 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1516 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1517 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1518 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1519 permutation |= SHADERPERMUTATION_REFLECTION;
1521 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1523 // directional model lighting
1524 mode = SHADERMODE_LIGHTDIRECTION;
1525 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1526 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1527 if (rsurface.texture->currentskinframe->glow)
1528 permutation |= SHADERPERMUTATION_GLOW;
1529 permutation |= SHADERPERMUTATION_DIFFUSE;
1530 if (specularscale > 0)
1531 permutation |= SHADERPERMUTATION_SPECULAR;
1532 if (r_refdef.fogenabled)
1533 permutation |= SHADERPERMUTATION_FOG;
1534 if (rsurface.texture->colormapping)
1535 permutation |= SHADERPERMUTATION_COLORMAPPING;
1536 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1537 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1538 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1539 permutation |= SHADERPERMUTATION_REFLECTION;
1541 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1543 // ambient model lighting
1544 mode = SHADERMODE_LIGHTDIRECTION;
1545 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1546 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1547 if (rsurface.texture->currentskinframe->glow)
1548 permutation |= SHADERPERMUTATION_GLOW;
1549 if (r_refdef.fogenabled)
1550 permutation |= SHADERPERMUTATION_FOG;
1551 if (rsurface.texture->colormapping)
1552 permutation |= SHADERPERMUTATION_COLORMAPPING;
1553 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1554 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1555 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1556 permutation |= SHADERPERMUTATION_REFLECTION;
1561 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1563 // deluxemapping (light direction texture)
1564 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1565 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1567 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1568 permutation |= SHADERPERMUTATION_DIFFUSE;
1569 if (specularscale > 0)
1570 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1572 else if (r_glsl_deluxemapping.integer >= 2)
1574 // fake deluxemapping (uniform light direction in tangentspace)
1575 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1576 permutation |= SHADERPERMUTATION_DIFFUSE;
1577 if (specularscale > 0)
1578 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1580 else if (rsurface.uselightmaptexture)
1582 // ordinary lightmapping (q1bsp, q3bsp)
1583 mode = SHADERMODE_LIGHTMAP;
1587 // ordinary vertex coloring (q3bsp)
1588 mode = SHADERMODE_VERTEXCOLOR;
1590 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1591 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1592 if (rsurface.texture->currentskinframe->glow)
1593 permutation |= SHADERPERMUTATION_GLOW;
1594 if (r_refdef.fogenabled)
1595 permutation |= SHADERPERMUTATION_FOG;
1596 if (rsurface.texture->colormapping)
1597 permutation |= SHADERPERMUTATION_COLORMAPPING;
1598 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1599 permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1600 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1601 permutation |= SHADERPERMUTATION_REFLECTION;
1603 R_SetupShader_SetPermutation(mode, permutation);
1604 if (mode == SHADERMODE_LIGHTSOURCE)
1606 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1607 if (permutation & SHADERPERMUTATION_DIFFUSE)
1609 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1610 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1611 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1612 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1616 // ambient only is simpler
1617 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]);
1618 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1619 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1620 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1622 // additive passes are only darkened by fog, not tinted
1623 if (r_glsl_permutation->loc_FogColor >= 0)
1624 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1628 if (mode == SHADERMODE_LIGHTDIRECTION)
1630 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);
1631 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);
1632 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);
1633 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]);
1637 if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1638 if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1639 if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1641 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]);
1642 if (r_glsl_permutation->loc_GlowScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1643 // additive passes are only darkened by fog, not tinted
1644 if (r_glsl_permutation->loc_FogColor >= 0)
1646 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1647 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1649 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1651 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);
1652 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]);
1653 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]);
1654 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1655 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1656 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1657 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1659 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1661 // The formula used is actually:
1662 // color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1663 // color.rgb *= SceneBrightness;
1665 // color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1666 // and do [[calculations]] here in the engine
1667 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1668 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1671 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1672 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1673 if (r_glsl_permutation->loc_Color_Pants >= 0)
1675 if (rsurface.texture->currentskinframe->pants)
1676 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1678 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1680 if (r_glsl_permutation->loc_Color_Shirt >= 0)
1682 if (rsurface.texture->currentskinframe->shirt)
1683 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1685 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1687 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1688 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1689 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1693 #define SKINFRAME_HASH 1024
1697 int loadsequence; // incremented each level change
1698 memexpandablearray_t array;
1699 skinframe_t *hash[SKINFRAME_HASH];
1703 void R_SkinFrame_PrepareForPurge(void)
1705 r_skinframe.loadsequence++;
1706 // wrap it without hitting zero
1707 if (r_skinframe.loadsequence >= 200)
1708 r_skinframe.loadsequence = 1;
1711 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1715 // mark the skinframe as used for the purging code
1716 skinframe->loadsequence = r_skinframe.loadsequence;
1719 void R_SkinFrame_Purge(void)
1723 for (i = 0;i < SKINFRAME_HASH;i++)
1725 for (s = r_skinframe.hash[i];s;s = s->next)
1727 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1729 if (s->merged == s->base)
1731 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1732 R_PurgeTexture(s->stain );s->stain = NULL;
1733 R_PurgeTexture(s->merged);s->merged = NULL;
1734 R_PurgeTexture(s->base );s->base = NULL;
1735 R_PurgeTexture(s->pants );s->pants = NULL;
1736 R_PurgeTexture(s->shirt );s->shirt = NULL;
1737 R_PurgeTexture(s->nmap );s->nmap = NULL;
1738 R_PurgeTexture(s->gloss );s->gloss = NULL;
1739 R_PurgeTexture(s->glow );s->glow = NULL;
1740 R_PurgeTexture(s->fog );s->fog = NULL;
1741 s->loadsequence = 0;
1747 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1749 char basename[MAX_QPATH];
1751 Image_StripImageExtension(name, basename, sizeof(basename));
1753 if( last == NULL ) {
1755 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1756 item = r_skinframe.hash[hashindex];
1761 // linearly search through the hash bucket
1762 for( ; item ; item = item->next ) {
1763 if( !strcmp( item->basename, basename ) ) {
1770 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1774 char basename[MAX_QPATH];
1776 Image_StripImageExtension(name, basename, sizeof(basename));
1778 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1779 for (item = r_skinframe.hash[hashindex];item;item = item->next)
1780 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1784 rtexture_t *dyntexture;
1785 // check whether its a dynamic texture
1786 dyntexture = CL_GetDynTexture( basename );
1787 if (!add && !dyntexture)
1789 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1790 memset(item, 0, sizeof(*item));
1791 strlcpy(item->basename, basename, sizeof(item->basename));
1792 item->base = dyntexture; // either NULL or dyntexture handle
1793 item->textureflags = textureflags;
1794 item->comparewidth = comparewidth;
1795 item->compareheight = compareheight;
1796 item->comparecrc = comparecrc;
1797 item->next = r_skinframe.hash[hashindex];
1798 r_skinframe.hash[hashindex] = item;
1800 else if( item->base == NULL )
1802 rtexture_t *dyntexture;
1803 // check whether its a dynamic texture
1804 // 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]
1805 dyntexture = CL_GetDynTexture( basename );
1806 item->base = dyntexture; // either NULL or dyntexture handle
1809 R_SkinFrame_MarkUsed(item);
1813 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1815 // FIXME: it should be possible to disable loading various layers using
1816 // cvars, to prevent wasted loading time and memory usage if the user does
1818 qboolean loadnormalmap = true;
1819 qboolean loadgloss = true;
1820 qboolean loadpantsandshirt = true;
1821 qboolean loadglow = true;
1823 unsigned char *pixels;
1824 unsigned char *bumppixels;
1825 unsigned char *basepixels = NULL;
1826 int basepixels_width;
1827 int basepixels_height;
1828 skinframe_t *skinframe;
1830 if (cls.state == ca_dedicated)
1833 // return an existing skinframe if already loaded
1834 // if loading of the first image fails, don't make a new skinframe as it
1835 // would cause all future lookups of this to be missing
1836 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1837 if (skinframe && skinframe->base)
1840 basepixels = loadimagepixelsbgra(name, complain, true);
1841 if (basepixels == NULL)
1844 // we've got some pixels to store, so really allocate this new texture now
1846 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1847 skinframe->stain = NULL;
1848 skinframe->merged = NULL;
1849 skinframe->base = r_texture_notexture;
1850 skinframe->pants = NULL;
1851 skinframe->shirt = NULL;
1852 skinframe->nmap = r_texture_blanknormalmap;
1853 skinframe->gloss = NULL;
1854 skinframe->glow = NULL;
1855 skinframe->fog = NULL;
1857 basepixels_width = image_width;
1858 basepixels_height = image_height;
1859 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);
1861 if (textureflags & TEXF_ALPHA)
1863 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1864 if (basepixels[j] < 255)
1866 if (j < basepixels_width * basepixels_height * 4)
1868 // has transparent pixels
1869 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1870 for (j = 0;j < image_width * image_height * 4;j += 4)
1875 pixels[j+3] = basepixels[j+3];
1877 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);
1882 // _norm is the name used by tenebrae and has been adopted as standard
1885 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1887 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);
1891 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1893 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1894 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1895 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);
1897 Mem_Free(bumppixels);
1899 else if (r_shadow_bumpscale_basetexture.value > 0)
1901 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1902 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1903 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);
1907 // _luma is supported for tenebrae compatibility
1908 // (I think it's a very stupid name, but oh well)
1909 // _glow is the preferred name
1910 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;}
1911 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;}
1912 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;}
1913 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;}
1916 Mem_Free(basepixels);
1921 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)
1926 for (i = 0;i < width*height;i++)
1927 if (((unsigned char *)&palette[in[i]])[3] > 0)
1929 if (i == width*height)
1932 return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1935 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1936 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1939 unsigned char *temp1, *temp2;
1940 skinframe_t *skinframe;
1942 if (cls.state == ca_dedicated)
1945 // if already loaded just return it, otherwise make a new skinframe
1946 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1947 if (skinframe && skinframe->base)
1950 skinframe->stain = NULL;
1951 skinframe->merged = NULL;
1952 skinframe->base = r_texture_notexture;
1953 skinframe->pants = NULL;
1954 skinframe->shirt = NULL;
1955 skinframe->nmap = r_texture_blanknormalmap;
1956 skinframe->gloss = NULL;
1957 skinframe->glow = NULL;
1958 skinframe->fog = NULL;
1960 // if no data was provided, then clearly the caller wanted to get a blank skinframe
1964 if (r_shadow_bumpscale_basetexture.value > 0)
1966 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
1967 temp2 = temp1 + width * height * 4;
1968 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
1969 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
1972 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1973 if (textureflags & TEXF_ALPHA)
1975 for (i = 3;i < width * height * 4;i += 4)
1976 if (skindata[i] < 255)
1978 if (i < width * height * 4)
1980 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
1981 memcpy(fogpixels, skindata, width * height * 4);
1982 for (i = 0;i < width * height * 4;i += 4)
1983 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
1984 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
1985 Mem_Free(fogpixels);
1992 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
1995 unsigned char *temp1, *temp2;
1996 skinframe_t *skinframe;
1998 if (cls.state == ca_dedicated)
2001 // if already loaded just return it, otherwise make a new skinframe
2002 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2003 if (skinframe && skinframe->base)
2006 skinframe->stain = NULL;
2007 skinframe->merged = NULL;
2008 skinframe->base = r_texture_notexture;
2009 skinframe->pants = NULL;
2010 skinframe->shirt = NULL;
2011 skinframe->nmap = r_texture_blanknormalmap;
2012 skinframe->gloss = NULL;
2013 skinframe->glow = NULL;
2014 skinframe->fog = NULL;
2016 // if no data was provided, then clearly the caller wanted to get a blank skinframe
2020 if (r_shadow_bumpscale_basetexture.value > 0)
2022 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2023 temp2 = temp1 + width * height * 4;
2024 // use either a custom palette or the quake palette
2025 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2026 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2027 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2030 // use either a custom palette, or the quake palette
2031 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
2032 if (loadglowtexture)
2033 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2034 if (loadpantsandshirt)
2036 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2037 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2039 if (skinframe->pants || skinframe->shirt)
2040 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
2041 if (textureflags & TEXF_ALPHA)
2043 for (i = 0;i < width * height;i++)
2044 if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2046 if (i < width * height)
2047 skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2053 skinframe_t *R_SkinFrame_LoadMissing(void)
2055 skinframe_t *skinframe;
2057 if (cls.state == ca_dedicated)
2060 skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2061 skinframe->stain = NULL;
2062 skinframe->merged = NULL;
2063 skinframe->base = r_texture_notexture;
2064 skinframe->pants = NULL;
2065 skinframe->shirt = NULL;
2066 skinframe->nmap = r_texture_blanknormalmap;
2067 skinframe->gloss = NULL;
2068 skinframe->glow = NULL;
2069 skinframe->fog = NULL;
2074 void gl_main_start(void)
2076 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2077 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2079 // set up r_skinframe loading system for textures
2080 memset(&r_skinframe, 0, sizeof(r_skinframe));
2081 r_skinframe.loadsequence = 1;
2082 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2084 r_main_texturepool = R_AllocTexturePool();
2085 R_BuildBlankTextures();
2087 if (gl_texturecubemap)
2090 R_BuildNormalizationCube();
2092 r_texture_fogattenuation = NULL;
2093 //r_texture_fogintensity = NULL;
2094 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2095 memset(&r_waterstate, 0, sizeof(r_waterstate));
2096 memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2097 memset(&r_svbsp, 0, sizeof (r_svbsp));
2099 r_refdef.fogmasktable_density = 0;
2102 void gl_main_shutdown(void)
2104 memset(r_qwskincache, 0, sizeof(r_qwskincache));
2105 memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2107 // clear out the r_skinframe state
2108 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2109 memset(&r_skinframe, 0, sizeof(r_skinframe));
2112 Mem_Free(r_svbsp.nodes);
2113 memset(&r_svbsp, 0, sizeof (r_svbsp));
2114 R_FreeTexturePool(&r_main_texturepool);
2115 r_texture_blanknormalmap = NULL;
2116 r_texture_white = NULL;
2117 r_texture_grey128 = NULL;
2118 r_texture_black = NULL;
2119 r_texture_whitecube = NULL;
2120 r_texture_normalizationcube = NULL;
2121 r_texture_fogattenuation = NULL;
2122 //r_texture_fogintensity = NULL;
2123 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2124 memset(&r_waterstate, 0, sizeof(r_waterstate));
2128 extern void CL_ParseEntityLump(char *entitystring);
2129 void gl_main_newmap(void)
2131 // FIXME: move this code to client
2133 char *entities, entname[MAX_QPATH];
2136 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2137 l = (int)strlen(entname) - 4;
2138 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2140 memcpy(entname + l, ".ent", 5);
2141 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2143 CL_ParseEntityLump(entities);
2148 if (cl.worldmodel->brush.entities)
2149 CL_ParseEntityLump(cl.worldmodel->brush.entities);
2153 void GL_Main_Init(void)
2155 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2157 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2158 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2159 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2160 if (gamemode == GAME_NEHAHRA)
2162 Cvar_RegisterVariable (&gl_fogenable);
2163 Cvar_RegisterVariable (&gl_fogdensity);
2164 Cvar_RegisterVariable (&gl_fogred);
2165 Cvar_RegisterVariable (&gl_foggreen);
2166 Cvar_RegisterVariable (&gl_fogblue);
2167 Cvar_RegisterVariable (&gl_fogstart);
2168 Cvar_RegisterVariable (&gl_fogend);
2169 Cvar_RegisterVariable (&gl_skyclip);
2171 Cvar_RegisterVariable(&r_depthfirst);
2172 Cvar_RegisterVariable(&r_nearclip);
2173 Cvar_RegisterVariable(&r_showbboxes);
2174 Cvar_RegisterVariable(&r_showsurfaces);
2175 Cvar_RegisterVariable(&r_showtris);
2176 Cvar_RegisterVariable(&r_shownormals);
2177 Cvar_RegisterVariable(&r_showlighting);
2178 Cvar_RegisterVariable(&r_showshadowvolumes);
2179 Cvar_RegisterVariable(&r_showcollisionbrushes);
2180 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2181 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2182 Cvar_RegisterVariable(&r_showdisabledepthtest);
2183 Cvar_RegisterVariable(&r_drawportals);
2184 Cvar_RegisterVariable(&r_drawentities);
2185 Cvar_RegisterVariable(&r_cullentities_trace);
2186 Cvar_RegisterVariable(&r_cullentities_trace_samples);
2187 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2188 Cvar_RegisterVariable(&r_cullentities_trace_delay);
2189 Cvar_RegisterVariable(&r_drawviewmodel);
2190 Cvar_RegisterVariable(&r_speeds);
2191 Cvar_RegisterVariable(&r_fullbrights);
2192 Cvar_RegisterVariable(&r_wateralpha);
2193 Cvar_RegisterVariable(&r_dynamic);
2194 Cvar_RegisterVariable(&r_fullbright);
2195 Cvar_RegisterVariable(&r_shadows);
2196 Cvar_RegisterVariable(&r_shadows_throwdistance);
2197 Cvar_RegisterVariable(&r_q1bsp_skymasking);
2198 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2199 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2200 Cvar_RegisterVariable(&r_fog_exp2);
2201 Cvar_RegisterVariable(&r_textureunits);
2202 Cvar_RegisterVariable(&r_glsl);
2203 Cvar_RegisterVariable(&r_glsl_offsetmapping);
2204 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2205 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2206 Cvar_RegisterVariable(&r_glsl_deluxemapping);
2207 Cvar_RegisterVariable(&r_glsl_usegeneric);
2208 Cvar_RegisterVariable(&r_water);
2209 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2210 Cvar_RegisterVariable(&r_water_clippingplanebias);
2211 Cvar_RegisterVariable(&r_water_refractdistort);
2212 Cvar_RegisterVariable(&r_water_reflectdistort);
2213 Cvar_RegisterVariable(&r_lerpsprites);
2214 Cvar_RegisterVariable(&r_lerpmodels);
2215 Cvar_RegisterVariable(&r_lerplightstyles);
2216 Cvar_RegisterVariable(&r_waterscroll);
2217 Cvar_RegisterVariable(&r_bloom);
2218 Cvar_RegisterVariable(&r_bloom_colorscale);
2219 Cvar_RegisterVariable(&r_bloom_brighten);
2220 Cvar_RegisterVariable(&r_bloom_blur);
2221 Cvar_RegisterVariable(&r_bloom_resolution);
2222 Cvar_RegisterVariable(&r_bloom_colorexponent);
2223 Cvar_RegisterVariable(&r_bloom_colorsubtract);
2224 Cvar_RegisterVariable(&r_hdr);
2225 Cvar_RegisterVariable(&r_hdr_scenebrightness);
2226 Cvar_RegisterVariable(&r_glsl_contrastboost);
2227 Cvar_RegisterVariable(&r_hdr_glowintensity);
2228 Cvar_RegisterVariable(&r_hdr_range);
2229 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2230 Cvar_RegisterVariable(&developer_texturelogging);
2231 Cvar_RegisterVariable(&gl_lightmaps);
2232 Cvar_RegisterVariable(&r_test);
2233 Cvar_RegisterVariable(&r_batchmode);
2234 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2235 Cvar_SetValue("r_fullbrights", 0);
2236 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2238 Cvar_RegisterVariable(&r_track_sprites);
2239 Cvar_RegisterVariable(&r_track_sprites_flags);
2240 Cvar_RegisterVariable(&r_track_sprites_scalew);
2241 Cvar_RegisterVariable(&r_track_sprites_scaleh);
2244 extern void R_Textures_Init(void);
2245 extern void GL_Draw_Init(void);
2246 extern void GL_Main_Init(void);
2247 extern void R_Shadow_Init(void);
2248 extern void R_Sky_Init(void);
2249 extern void GL_Surf_Init(void);
2250 extern void R_Particles_Init(void);
2251 extern void R_Explosion_Init(void);
2252 extern void gl_backend_init(void);
2253 extern void Sbar_Init(void);
2254 extern void R_LightningBeams_Init(void);
2255 extern void Mod_RenderInit(void);
2257 void Render_Init(void)
2269 R_LightningBeams_Init();
2278 extern char *ENGINE_EXTENSIONS;
2281 VID_CheckExtensions();
2283 // LordHavoc: report supported extensions
2284 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2286 // clear to black (loading plaque will be seen over this)
2288 qglClearColor(0,0,0,1);CHECKGLERROR
2289 qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2292 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2296 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2298 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2301 p = r_refdef.view.frustum + i;
2306 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2310 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2314 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2318 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2322 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2326 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2330 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2334 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2342 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2346 for (i = 0;i < numplanes;i++)
2353 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2357 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2361 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2365 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2369 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2373 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2377 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2381 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2389 //==================================================================================
2391 static void R_View_UpdateEntityVisible (void)
2394 entity_render_t *ent;
2396 if (!r_drawentities.integer)
2399 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2400 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2402 // worldmodel can check visibility
2403 for (i = 0;i < r_refdef.scene.numentities;i++)
2405 ent = r_refdef.scene.entities[i];
2406 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));
2409 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2411 for (i = 0;i < r_refdef.scene.numentities;i++)
2413 ent = r_refdef.scene.entities[i];
2414 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2416 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))
2417 ent->last_trace_visibility = realtime;
2418 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2419 r_refdef.viewcache.entityvisible[i] = 0;
2426 // no worldmodel or it can't check visibility
2427 for (i = 0;i < r_refdef.scene.numentities;i++)
2429 ent = r_refdef.scene.entities[i];
2430 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));
2435 // only used if skyrendermasked, and normally returns false
2436 int R_DrawBrushModelsSky (void)
2439 entity_render_t *ent;
2441 if (!r_drawentities.integer)
2445 for (i = 0;i < r_refdef.scene.numentities;i++)
2447 if (!r_refdef.viewcache.entityvisible[i])
2449 ent = r_refdef.scene.entities[i];
2450 if (!ent->model || !ent->model->DrawSky)
2452 ent->model->DrawSky(ent);
2458 static void R_DrawNoModel(entity_render_t *ent);
2459 static void R_DrawModels(void)
2462 entity_render_t *ent;
2464 if (!r_drawentities.integer)
2467 for (i = 0;i < r_refdef.scene.numentities;i++)
2469 if (!r_refdef.viewcache.entityvisible[i])
2471 ent = r_refdef.scene.entities[i];
2472 r_refdef.stats.entities++;
2473 if (ent->model && ent->model->Draw != NULL)
2474 ent->model->Draw(ent);
2480 static void R_DrawModelsDepth(void)
2483 entity_render_t *ent;
2485 if (!r_drawentities.integer)
2488 for (i = 0;i < r_refdef.scene.numentities;i++)
2490 if (!r_refdef.viewcache.entityvisible[i])
2492 ent = r_refdef.scene.entities[i];
2493 if (ent->model && ent->model->DrawDepth != NULL)
2494 ent->model->DrawDepth(ent);
2498 static void R_DrawModelsDebug(void)
2501 entity_render_t *ent;
2503 if (!r_drawentities.integer)
2506 for (i = 0;i < r_refdef.scene.numentities;i++)
2508 if (!r_refdef.viewcache.entityvisible[i])
2510 ent = r_refdef.scene.entities[i];
2511 if (ent->model && ent->model->DrawDebug != NULL)
2512 ent->model->DrawDebug(ent);
2516 static void R_DrawModelsAddWaterPlanes(void)
2519 entity_render_t *ent;
2521 if (!r_drawentities.integer)
2524 for (i = 0;i < r_refdef.scene.numentities;i++)
2526 if (!r_refdef.viewcache.entityvisible[i])
2528 ent = r_refdef.scene.entities[i];
2529 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2530 ent->model->DrawAddWaterPlanes(ent);
2534 static void R_View_SetFrustum(void)
2537 double slopex, slopey;
2538 vec3_t forward, left, up, origin;
2540 // we can't trust r_refdef.view.forward and friends in reflected scenes
2541 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2544 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2545 r_refdef.view.frustum[0].normal[1] = 0 - 0;
2546 r_refdef.view.frustum[0].normal[2] = -1 - 0;
2547 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2548 r_refdef.view.frustum[1].normal[1] = 0 + 0;
2549 r_refdef.view.frustum[1].normal[2] = -1 + 0;
2550 r_refdef.view.frustum[2].normal[0] = 0 - 0;
2551 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2552 r_refdef.view.frustum[2].normal[2] = -1 - 0;
2553 r_refdef.view.frustum[3].normal[0] = 0 + 0;
2554 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2555 r_refdef.view.frustum[3].normal[2] = -1 + 0;
2559 zNear = r_refdef.nearclip;
2560 nudge = 1.0 - 1.0 / (1<<23);
2561 r_refdef.view.frustum[4].normal[0] = 0 - 0;
2562 r_refdef.view.frustum[4].normal[1] = 0 - 0;
2563 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2564 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2565 r_refdef.view.frustum[5].normal[0] = 0 + 0;
2566 r_refdef.view.frustum[5].normal[1] = 0 + 0;
2567 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2568 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2574 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2575 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2576 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2577 r_refdef.view.frustum[0].dist = m[15] - m[12];
2579 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2580 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2581 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2582 r_refdef.view.frustum[1].dist = m[15] + m[12];
2584 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2585 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2586 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2587 r_refdef.view.frustum[2].dist = m[15] - m[13];
2589 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2590 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2591 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2592 r_refdef.view.frustum[3].dist = m[15] + m[13];
2594 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2595 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2596 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2597 r_refdef.view.frustum[4].dist = m[15] - m[14];
2599 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2600 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2601 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2602 r_refdef.view.frustum[5].dist = m[15] + m[14];
2605 if (r_refdef.view.useperspective)
2607 slopex = 1.0 / r_refdef.view.frustum_x;
2608 slopey = 1.0 / r_refdef.view.frustum_y;
2609 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2610 VectorMA(forward, slopex, left, r_refdef.view.frustum[1].normal);
2611 VectorMA(forward, -slopey, up , r_refdef.view.frustum[2].normal);
2612 VectorMA(forward, slopey, up , r_refdef.view.frustum[3].normal);
2613 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2615 // Leaving those out was a mistake, those were in the old code, and they
2616 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2617 // I couldn't reproduce it after adding those normalizations. --blub
2618 VectorNormalize(r_refdef.view.frustum[0].normal);
2619 VectorNormalize(r_refdef.view.frustum[1].normal);
2620 VectorNormalize(r_refdef.view.frustum[2].normal);
2621 VectorNormalize(r_refdef.view.frustum[3].normal);
2623 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2624 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2625 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2626 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2627 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, 1024 * slopex, left, 1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2629 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2630 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2631 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2632 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2633 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2637 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2638 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2639 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2640 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2641 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2642 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2643 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2644 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2645 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2646 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2648 r_refdef.view.numfrustumplanes = 5;
2650 if (r_refdef.view.useclipplane)
2652 r_refdef.view.numfrustumplanes = 6;
2653 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2656 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2657 PlaneClassify(r_refdef.view.frustum + i);
2659 // LordHavoc: note to all quake engine coders, Quake had a special case
2660 // for 90 degrees which assumed a square view (wrong), so I removed it,
2661 // Quake2 has it disabled as well.
2663 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2664 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2665 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2666 //PlaneClassify(&frustum[0]);
2668 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2669 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2670 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2671 //PlaneClassify(&frustum[1]);
2673 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2674 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2675 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2676 //PlaneClassify(&frustum[2]);
2678 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2679 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2680 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2681 //PlaneClassify(&frustum[3]);
2684 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2685 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2686 //PlaneClassify(&frustum[4]);
2689 void R_View_Update(void)
2691 R_View_SetFrustum();
2692 R_View_WorldVisibility(r_refdef.view.useclipplane);
2693 R_View_UpdateEntityVisible();
2696 void R_SetupView(qboolean allowwaterclippingplane)
2698 if (!r_refdef.view.useperspective)
2699 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);
2700 else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2701 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2703 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2705 GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2707 if (r_refdef.view.useclipplane && allowwaterclippingplane)
2709 // LordHavoc: couldn't figure out how to make this approach the
2710 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2711 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2712 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2713 dist = r_refdef.view.clipplane.dist;
2714 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2718 void R_ResetViewRendering2D(void)
2722 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2723 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2724 GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2725 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2726 GL_Color(1, 1, 1, 1);
2727 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2728 GL_BlendFunc(GL_ONE, GL_ZERO);
2729 GL_AlphaTest(false);
2730 GL_ScissorTest(false);
2731 GL_DepthMask(false);
2732 GL_DepthRange(0, 1);
2733 GL_DepthTest(false);
2734 R_Mesh_Matrix(&identitymatrix);
2735 R_Mesh_ResetTextureState();
2736 GL_PolygonOffset(0, 0);
2737 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2738 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2739 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2740 qglStencilMask(~0);CHECKGLERROR
2741 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2742 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2743 GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2744 R_SetupGenericShader(true);
2747 void R_ResetViewRendering3D(void)
2751 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2752 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2754 GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2755 GL_Color(1, 1, 1, 1);
2756 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2757 GL_BlendFunc(GL_ONE, GL_ZERO);
2758 GL_AlphaTest(false);
2759 GL_ScissorTest(true);
2761 GL_DepthRange(0, 1);
2763 R_Mesh_Matrix(&identitymatrix);
2764 R_Mesh_ResetTextureState();
2765 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2766 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2767 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2768 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2769 qglStencilMask(~0);CHECKGLERROR
2770 qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2771 qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2772 GL_CullFace(r_refdef.view.cullface_back);
2773 R_SetupGenericShader(true);
2777 R_Bloom_SetupShader(
2779 "// written by Forest 'LordHavoc' Hale\n"
2781 "// common definitions between vertex shader and fragment shader:\n"
2783 "#ifdef __GLSL_CG_DATA_TYPES\n"
2784 "#define myhalf half\n"
2785 "#define myhalf2 half2\n"
2786 "#define myhalf3 half3\n"
2787 "#define myhalf4 half4\n"
2789 "#define myhalf float\n"
2790 "#define myhalf2 vec2\n"
2791 "#define myhalf3 vec3\n"
2792 "#define myhalf4 vec4\n"
2795 "varying vec2 ScreenTexCoord;\n"
2796 "varying vec2 BloomTexCoord;\n"
2801 "// vertex shader specific:\n"
2802 "#ifdef VERTEX_SHADER\n"
2806 " ScreenTexCoord = vec2(gl_MultiTexCoord0);\n"
2807 " BloomTexCoord = vec2(gl_MultiTexCoord1);\n"
2808 " // transform vertex to camera space, using ftransform to match non-VS\n"
2810 " gl_Position = ftransform();\n"
2813 "#endif // VERTEX_SHADER\n"
2818 "// fragment shader specific:\n"
2819 "#ifdef FRAGMENT_SHADER\n"
2824 " myhalf3 color = myhalf3(texture2D(Texture_Screen, ScreenTexCoord));\n"
2825 " for (x = -BLUR_X;x <= BLUR_X;x++)
2826 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2827 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2828 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2829 " color.rgb += myhalf3(texture2D(Texture_Bloom, BloomTexCoord));\n"
2831 " gl_FragColor = vec4(color);\n"
2834 "#endif // FRAGMENT_SHADER\n"
2837 void R_RenderScene(qboolean addwaterplanes);
2839 static void R_Water_StartFrame(void)
2842 int waterwidth, waterheight, texturewidth, textureheight;
2843 r_waterstate_waterplane_t *p;
2845 // set waterwidth and waterheight to the water resolution that will be
2846 // used (often less than the screen resolution for faster rendering)
2847 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2848 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2850 // calculate desired texture sizes
2851 // can't use water if the card does not support the texture size
2852 if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2853 texturewidth = textureheight = waterwidth = waterheight = 0;
2854 else if (gl_support_arb_texture_non_power_of_two)
2856 texturewidth = waterwidth;
2857 textureheight = waterheight;
2861 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
2862 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
2865 // allocate textures as needed
2866 if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2868 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2869 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2871 if (p->texture_refraction)
2872 R_FreeTexture(p->texture_refraction);
2873 p->texture_refraction = NULL;
2874 if (p->texture_reflection)
2875 R_FreeTexture(p->texture_reflection);
2876 p->texture_reflection = NULL;
2878 memset(&r_waterstate, 0, sizeof(r_waterstate));
2879 r_waterstate.waterwidth = waterwidth;
2880 r_waterstate.waterheight = waterheight;
2881 r_waterstate.texturewidth = texturewidth;
2882 r_waterstate.textureheight = textureheight;
2885 if (r_waterstate.waterwidth)
2887 r_waterstate.enabled = true;
2889 // set up variables that will be used in shader setup
2890 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2891 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2892 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2893 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2896 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2897 r_waterstate.numwaterplanes = 0;
2900 static void R_Water_AddWaterPlane(msurface_t *surface)
2902 int triangleindex, planeindex;
2907 r_waterstate_waterplane_t *p;
2908 // just use the first triangle with a valid normal for any decisions
2909 VectorClear(normal);
2910 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2912 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2913 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2914 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2915 TriangleNormal(vert[0], vert[1], vert[2], normal);
2916 if (VectorLength2(normal) >= 0.001)
2920 // find a matching plane if there is one
2921 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2922 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2924 if (planeindex >= r_waterstate.maxwaterplanes)
2925 return; // nothing we can do, out of planes
2927 // if this triangle does not fit any known plane rendered this frame, add one
2928 if (planeindex >= r_waterstate.numwaterplanes)
2930 // store the new plane
2931 r_waterstate.numwaterplanes++;
2932 VectorCopy(normal, p->plane.normal);
2933 VectorNormalize(p->plane.normal);
2934 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2935 PlaneClassify(&p->plane);
2936 // flip the plane if it does not face the viewer
2937 if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0)
2939 VectorNegate(p->plane.normal, p->plane.normal);
2940 p->plane.dist *= -1;
2941 PlaneClassify(&p->plane);
2943 // clear materialflags and pvs
2944 p->materialflags = 0;
2945 p->pvsvalid = false;
2947 // merge this surface's materialflags into the waterplane
2948 p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2949 // merge this surface's PVS into the waterplane
2950 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2951 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
2952 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
2954 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2959 static void R_Water_ProcessPlanes(void)
2961 r_refdef_view_t originalview;
2963 r_waterstate_waterplane_t *p;
2965 originalview = r_refdef.view;
2967 // make sure enough textures are allocated
2968 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2970 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2972 if (!p->texture_refraction)
2973 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);
2974 if (!p->texture_refraction)
2978 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2980 if (!p->texture_reflection)
2981 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);
2982 if (!p->texture_reflection)
2988 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2990 r_refdef.view.showdebug = false;
2991 r_refdef.view.width = r_waterstate.waterwidth;
2992 r_refdef.view.height = r_waterstate.waterheight;
2993 r_refdef.view.useclipplane = true;
2994 r_waterstate.renderingscene = true;
2996 // render the normal view scene and copy into texture
2997 // (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)
2998 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
3000 r_refdef.view.clipplane = p->plane;
3001 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
3002 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
3003 PlaneClassify(&r_refdef.view.clipplane);
3005 R_RenderScene(false);
3007 // copy view into the screen texture
3008 R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
3009 GL_ActiveTexture(0);
3011 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
3014 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
3016 // render reflected scene and copy into texture
3017 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
3018 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3019 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3020 r_refdef.view.clipplane = p->plane;
3021 // reverse the cullface settings for this render
3022 r_refdef.view.cullface_front = GL_FRONT;
3023 r_refdef.view.cullface_back = GL_BACK;
3024 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3026 r_refdef.view.usecustompvs = true;
3028 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3030 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3033 R_ResetViewRendering3D();
3034 R_ClearScreen(r_refdef.fogenabled);
3035 if (r_timereport_active)
3036 R_TimeReport("viewclear");
3038 R_RenderScene(false);
3040 R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3041 GL_ActiveTexture(0);
3043 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
3045 R_ResetViewRendering3D();
3046 R_ClearScreen(r_refdef.fogenabled);
3047 if (r_timereport_active)
3048 R_TimeReport("viewclear");
3051 r_refdef.view = originalview;
3052 r_refdef.view.clear = true;
3053 r_waterstate.renderingscene = false;
3057 r_refdef.view = originalview;
3058 r_waterstate.renderingscene = false;
3059 Cvar_SetValueQuick(&r_water, 0);
3060 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
3064 void R_Bloom_StartFrame(void)
3066 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3068 // set bloomwidth and bloomheight to the bloom resolution that will be
3069 // used (often less than the screen resolution for faster rendering)
3070 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3071 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3072 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3074 // calculate desired texture sizes
3075 if (gl_support_arb_texture_non_power_of_two)
3077 screentexturewidth = r_refdef.view.width;
3078 screentextureheight = r_refdef.view.height;
3079 bloomtexturewidth = r_bloomstate.bloomwidth;
3080 bloomtextureheight = r_bloomstate.bloomheight;
3084 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
3085 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
3086 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
3087 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
3092 screentexturewidth = screentextureheight = 0;
3094 else if (r_bloom.integer)
3099 screentexturewidth = screentextureheight = 0;
3100 bloomtexturewidth = bloomtextureheight = 0;
3103 if ((!bloomtexturewidth && !bloomtextureheight) || r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512 || screentexturewidth > gl_max_texture_size || screentextureheight > gl_max_texture_size || bloomtexturewidth > gl_max_texture_size || bloomtextureheight > gl_max_texture_size)
3105 // can't use bloom if the parameters are too weird
3106 // can't use bloom if the card does not support the texture size
3107 if (r_bloomstate.texture_screen)
3108 R_FreeTexture(r_bloomstate.texture_screen);
3109 if (r_bloomstate.texture_bloom)
3110 R_FreeTexture(r_bloomstate.texture_bloom);
3111 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3115 r_bloomstate.enabled = true;
3116 r_bloomstate.hdr = r_hdr.integer != 0;
3118 // allocate textures as needed
3119 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3121 if (r_bloomstate.texture_screen)
3122 R_FreeTexture(r_bloomstate.texture_screen);
3123 r_bloomstate.texture_screen = NULL;
3124 r_bloomstate.screentexturewidth = screentexturewidth;
3125 r_bloomstate.screentextureheight = screentextureheight;
3126 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3127 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);
3129 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3131 if (r_bloomstate.texture_bloom)
3132 R_FreeTexture(r_bloomstate.texture_bloom);
3133 r_bloomstate.texture_bloom = NULL;
3134 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3135 r_bloomstate.bloomtextureheight = bloomtextureheight;
3136 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3137 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);
3140 // set up a texcoord array for the full resolution screen image
3141 // (we have to keep this around to copy back during final render)
3142 r_bloomstate.screentexcoord2f[0] = 0;
3143 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3144 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3145 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
3146 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
3147 r_bloomstate.screentexcoord2f[5] = 0;
3148 r_bloomstate.screentexcoord2f[6] = 0;
3149 r_bloomstate.screentexcoord2f[7] = 0;
3151 // set up a texcoord array for the reduced resolution bloom image
3152 // (which will be additive blended over the screen image)
3153 r_bloomstate.bloomtexcoord2f[0] = 0;
3154 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3155 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3156 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3157 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3158 r_bloomstate.bloomtexcoord2f[5] = 0;
3159 r_bloomstate.bloomtexcoord2f[6] = 0;
3160 r_bloomstate.bloomtexcoord2f[7] = 0;
3163 void R_Bloom_CopyScreenTexture(float colorscale)
3165 r_refdef.stats.bloom++;
3167 R_ResetViewRendering2D();
3168 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3169 R_Mesh_ColorPointer(NULL, 0, 0);
3170 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3171 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3172 R_SetupGenericShader(true);
3174 // copy view into the screen texture
3175 GL_ActiveTexture(0);
3177 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
3178 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3180 // now scale it down to the bloom texture size
3182 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3183 GL_BlendFunc(GL_ONE, GL_ZERO);
3184 GL_Color(colorscale, colorscale, colorscale, 1);
3185 // TODO: optimize with multitexture or GLSL
3186 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3187 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3189 // we now have a bloom image in the framebuffer
3190 // copy it into the bloom image texture for later processing
3191 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3192 GL_ActiveTexture(0);
3194 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
3195 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3198 void R_Bloom_CopyHDRTexture(void)
3200 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3201 GL_ActiveTexture(0);
3203 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
3204 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3207 void R_Bloom_MakeTexture(void)
3210 float xoffset, yoffset, r, brighten;
3212 r_refdef.stats.bloom++;
3214 R_ResetViewRendering2D();
3215 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3216 R_Mesh_ColorPointer(NULL, 0, 0);
3217 R_SetupGenericShader(true);
3219 // we have a bloom image in the framebuffer
3221 qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3223 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3226 r = bound(0, r_bloom_colorexponent.value / x, 1);
3227 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3228 GL_Color(r, r, r, 1);
3229 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3230 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3231 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3232 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3234 // copy the vertically blurred bloom view to a texture
3235 GL_ActiveTexture(0);
3237 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
3238 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3241 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3242 brighten = r_bloom_brighten.value;
3244 brighten *= r_hdr_range.value;
3245 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3246 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3248 for (dir = 0;dir < 2;dir++)
3250 // blend on at multiple vertical offsets to achieve a vertical blur
3251 // TODO: do offset blends using GLSL
3252 GL_BlendFunc(GL_ONE, GL_ZERO);
3253 for (x = -range;x <= range;x++)
3255 if (!dir){xoffset = 0;yoffset = x;}
3256 else {xoffset = x;yoffset = 0;}
3257 xoffset /= (float)r_bloomstate.bloomtexturewidth;
3258 yoffset /= (float)r_bloomstate.bloomtextureheight;
3259 // compute a texcoord array with the specified x and y offset
3260 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3261 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3262 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3263 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3264 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3265 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3266 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3267 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3268 // this r value looks like a 'dot' particle, fading sharply to
3269 // black at the edges
3270 // (probably not realistic but looks good enough)
3271 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3272 //r = (dir ? 1.0f : brighten)/(range*2+1);
3273 r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3274 GL_Color(r, r, r, 1);
3275 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3276 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3277 GL_BlendFunc(GL_ONE, GL_ONE);
3280 // copy the vertically blurred bloom view to a texture
3281 GL_ActiveTexture(0);
3283 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
3284 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3287 // apply subtract last
3288 // (just like it would be in a GLSL shader)
3289 if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3291 GL_BlendFunc(GL_ONE, GL_ZERO);
3292 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3293 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3294 GL_Color(1, 1, 1, 1);
3295 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3296 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3298 GL_BlendFunc(GL_ONE, GL_ONE);
3299 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3300 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3301 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3302 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3303 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3304 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3305 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3307 // copy the darkened bloom view to a texture
3308 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3309 GL_ActiveTexture(0);
3311 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
3312 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3316 void R_HDR_RenderBloomTexture(void)
3318 int oldwidth, oldheight;
3319 float oldcolorscale;
3321 oldcolorscale = r_refdef.view.colorscale;
3322 oldwidth = r_refdef.view.width;
3323 oldheight = r_refdef.view.height;
3324 r_refdef.view.width = r_bloomstate.bloomwidth;
3325 r_refdef.view.height = r_bloomstate.bloomheight;
3327 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
3328 // TODO: add exposure compensation features
3329 // TODO: add fp16 framebuffer support
3331 r_refdef.view.showdebug = false;
3332 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3334 R_ClearScreen(r_refdef.fogenabled);
3335 if (r_timereport_active)
3336 R_TimeReport("HDRclear");
3338 r_waterstate.numwaterplanes = 0;
3339 R_RenderScene(r_waterstate.enabled);
3340 r_refdef.view.showdebug = true;
3342 R_ResetViewRendering2D();
3344 R_Bloom_CopyHDRTexture();
3345 R_Bloom_MakeTexture();
3347 // restore the view settings
3348 r_refdef.view.width = oldwidth;
3349 r_refdef.view.height = oldheight;
3350 r_refdef.view.colorscale = oldcolorscale;
3352 R_ResetViewRendering3D();
3354 R_ClearScreen(r_refdef.fogenabled);
3355 if (r_timereport_active)
3356 R_TimeReport("viewclear");
3359 static void R_BlendView(void)
3361 if (r_bloomstate.enabled && r_bloomstate.hdr)
3363 // render high dynamic range bloom effect
3364 // the bloom texture was made earlier this render, so we just need to
3365 // blend it onto the screen...
3366 R_ResetViewRendering2D();
3367 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3368 R_Mesh_ColorPointer(NULL, 0, 0);
3369 R_SetupGenericShader(true);
3370 GL_Color(1, 1, 1, 1);
3371 GL_BlendFunc(GL_ONE, GL_ONE);
3372 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3373 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3374 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3375 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3377 else if (r_bloomstate.enabled)
3379 // render simple bloom effect
3380 // copy the screen and shrink it and darken it for the bloom process
3381 R_Bloom_CopyScreenTexture(r_bloom_colorscale.value);
3382 // make the bloom texture
3383 R_Bloom_MakeTexture();
3384 // put the original screen image back in place and blend the bloom
3386 R_ResetViewRendering2D();
3387 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3388 R_Mesh_ColorPointer(NULL, 0, 0);
3389 GL_Color(1, 1, 1, 1);
3390 GL_BlendFunc(GL_ONE, GL_ZERO);
3391 // do both in one pass if possible
3392 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3393 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3394 if (r_textureunits.integer >= 2 && gl_combine.integer)
3396 R_SetupGenericTwoTextureShader(GL_ADD);
3397 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3398 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3402 R_SetupGenericShader(true);
3403 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3404 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3405 // now blend on the bloom texture
3406 GL_BlendFunc(GL_ONE, GL_ONE);
3407 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3408 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3410 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3411 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3413 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3415 // apply a color tint to the whole view
3416 R_ResetViewRendering2D();
3417 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3418 R_Mesh_ColorPointer(NULL, 0, 0);
3419 R_SetupGenericShader(false);
3420 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3421 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3422 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3426 void R_RenderScene(qboolean addwaterplanes);
3428 matrix4x4_t r_waterscrollmatrix;
3430 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3432 if (r_refdef.fog_density)
3434 r_refdef.fogcolor[0] = r_refdef.fog_red;
3435 r_refdef.fogcolor[1] = r_refdef.fog_green;
3436 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3440 VectorCopy(r_refdef.fogcolor, fogvec);
3441 if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3443 // color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3444 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3445 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3446 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3448 // color.rgb *= ContrastBoost * SceneBrightness;
3449 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3450 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3451 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3452 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3457 void R_UpdateVariables(void)
3461 r_refdef.farclip = 4096;
3462 if (r_refdef.scene.worldmodel)
3463 r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3464 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3466 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3467 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3468 r_refdef.polygonfactor = 0;
3469 r_refdef.polygonoffset = 0;
3470 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3471 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3473 r_refdef.rtworld = r_shadow_realtime_world.integer;
3474 r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3475 r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3476 r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3477 r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3478 if (r_showsurfaces.integer)
3480 r_refdef.rtworld = false;
3481 r_refdef.rtworldshadows = false;
3482 r_refdef.rtdlight = false;
3483 r_refdef.rtdlightshadows = false;
3484 r_refdef.lightmapintensity = 0;
3487 if (gamemode == GAME_NEHAHRA)
3489 if (gl_fogenable.integer)
3491 r_refdef.oldgl_fogenable = true;
3492 r_refdef.fog_density = gl_fogdensity.value;
3493 r_refdef.fog_red = gl_fogred.value;
3494 r_refdef.fog_green = gl_foggreen.value;
3495 r_refdef.fog_blue = gl_fogblue.value;
3496 r_refdef.fog_alpha = 1;
3497 r_refdef.fog_start = 0;
3498 r_refdef.fog_end = gl_skyclip.value;
3500 else if (r_refdef.oldgl_fogenable)
3502 r_refdef.oldgl_fogenable = false;
3503 r_refdef.fog_density = 0;
3504 r_refdef.fog_red = 0;
3505 r_refdef.fog_green = 0;
3506 r_refdef.fog_blue = 0;
3507 r_refdef.fog_alpha = 0;
3508 r_refdef.fog_start = 0;
3509 r_refdef.fog_end = 0;
3513 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3514 r_refdef.fog_start = max(0, r_refdef.fog_start);
3515 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3517 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3519 if (r_refdef.fog_density)
3521 r_refdef.fogenabled = true;
3522 // this is the point where the fog reaches 0.9986 alpha, which we
3523 // consider a good enough cutoff point for the texture
3524 // (0.9986 * 256 == 255.6)
3525 if (r_fog_exp2.integer)
3526 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3528 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3529 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3530 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3531 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3532 // fog color was already set
3533 // update the fog texture
3534 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)
3535 R_BuildFogTexture();
3538 r_refdef.fogenabled = false;
3541 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3542 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3548 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3549 if( scenetype != r_currentscenetype ) {
3550 // store the old scenetype
3551 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3552 r_currentscenetype = scenetype;
3553 // move in the new scene
3554 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3563 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3565 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3566 if( scenetype == r_currentscenetype ) {
3567 return &r_refdef.scene;
3569 return &r_scenes_store[ scenetype ];
3578 void R_RenderView(void)
3580 if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
3581 return; //Host_Error ("R_RenderView: NULL worldmodel");
3583 r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3585 // break apart the view matrix into vectors for various purposes
3586 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3587 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3588 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3589 VectorNegate(r_refdef.view.left, r_refdef.view.right);
3590 // make an inverted copy of the view matrix for tracking sprites
3591 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3593 R_Shadow_UpdateWorldLightSelection();
3595 R_Bloom_StartFrame();
3596 R_Water_StartFrame();
3599 if (r_timereport_active)
3600 R_TimeReport("viewsetup");
3602 R_ResetViewRendering3D();
3604 if (r_refdef.view.clear || r_refdef.fogenabled)
3606 R_ClearScreen(r_refdef.fogenabled);
3607 if (r_timereport_active)
3608 R_TimeReport("viewclear");
3610 r_refdef.view.clear = true;
3612 r_refdef.view.showdebug = true;
3614 // this produces a bloom texture to be used in R_BlendView() later
3616 R_HDR_RenderBloomTexture();
3618 r_waterstate.numwaterplanes = 0;
3619 R_RenderScene(r_waterstate.enabled);
3622 if (r_timereport_active)
3623 R_TimeReport("blendview");
3625 GL_Scissor(0, 0, vid.width, vid.height);
3626 GL_ScissorTest(false);
3630 extern void R_DrawLightningBeams (void);
3631 extern void VM_CL_AddPolygonsToMeshQueue (void);
3632 extern void R_DrawPortals (void);
3633 extern cvar_t cl_locs_show;
3634 static void R_DrawLocs(void);
3635 static void R_DrawEntityBBoxes(void);
3636 void R_RenderScene(qboolean addwaterplanes)
3638 r_refdef.stats.renders++;
3644 R_ResetViewRendering3D();
3647 if (r_timereport_active)
3648 R_TimeReport("watervis");
3650 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3652 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3653 if (r_timereport_active)
3654 R_TimeReport("waterworld");
3657 // don't let sound skip if going slow
3658 if (r_refdef.scene.extraupdate)
3661 R_DrawModelsAddWaterPlanes();
3662 if (r_timereport_active)
3663 R_TimeReport("watermodels");
3665 R_Water_ProcessPlanes();
3666 if (r_timereport_active)
3667 R_TimeReport("waterscenes");
3670 R_ResetViewRendering3D();
3672 // don't let sound skip if going slow
3673 if (r_refdef.scene.extraupdate)
3676 R_MeshQueue_BeginScene();
3681 if (r_timereport_active)
3682 R_TimeReport("visibility");
3684 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);
3686 if (cl.csqc_vidvars.drawworld)
3688 // don't let sound skip if going slow
3689 if (r_refdef.scene.extraupdate)
3692 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3694 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3695 if (r_timereport_active)
3696 R_TimeReport("worldsky");
3699 if (R_DrawBrushModelsSky() && r_timereport_active)
3700 R_TimeReport("bmodelsky");
3703 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3705 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3706 if (r_timereport_active)
3707 R_TimeReport("worlddepth");
3709 if (r_depthfirst.integer >= 2)
3711 R_DrawModelsDepth();
3712 if (r_timereport_active)
3713 R_TimeReport("modeldepth");
3716 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3718 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3719 if (r_timereport_active)
3720 R_TimeReport("world");
3723 // don't let sound skip if going slow
3724 if (r_refdef.scene.extraupdate)
3728 if (r_timereport_active)
3729 R_TimeReport("models");
3731 // don't let sound skip if going slow
3732 if (r_refdef.scene.extraupdate)
3735 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3737 R_DrawModelShadows();
3739 R_ResetViewRendering3D();
3741 // don't let sound skip if going slow
3742 if (r_refdef.scene.extraupdate)
3746 R_ShadowVolumeLighting(false);
3747 if (r_timereport_active)
3748 R_TimeReport("rtlights");
3750 // don't let sound skip if going slow
3751 if (r_refdef.scene.extraupdate)
3754 if (cl.csqc_vidvars.drawworld)
3756 R_DrawLightningBeams();
3757 if (r_timereport_active)
3758 R_TimeReport("lightning");
3761 if (r_timereport_active)
3762 R_TimeReport("decals");
3765 if (r_timereport_active)
3766 R_TimeReport("particles");
3769 if (r_timereport_active)
3770 R_TimeReport("explosions");
3773 R_SetupGenericShader(true);
3774 VM_CL_AddPolygonsToMeshQueue();
3776 if (r_refdef.view.showdebug)
3778 if (cl_locs_show.integer)
3781 if (r_timereport_active)
3782 R_TimeReport("showlocs");
3785 if (r_drawportals.integer)
3788 if (r_timereport_active)
3789 R_TimeReport("portals");
3792 if (r_showbboxes.value > 0)
3794 R_DrawEntityBBoxes();
3795 if (r_timereport_active)
3796 R_TimeReport("bboxes");
3800 R_SetupGenericShader(true);
3801 R_MeshQueue_RenderTransparent();
3802 if (r_timereport_active)
3803 R_TimeReport("drawtrans");
3805 R_SetupGenericShader(true);
3807 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))
3809 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
3810 if (r_timereport_active)
3811 R_TimeReport("worlddebug");
3812 R_DrawModelsDebug();
3813 if (r_timereport_active)
3814 R_TimeReport("modeldebug");
3817 R_SetupGenericShader(true);
3819 if (cl.csqc_vidvars.drawworld)
3822 if (r_timereport_active)
3823 R_TimeReport("coronas");
3826 // don't let sound skip if going slow
3827 if (r_refdef.scene.extraupdate)
3830 R_ResetViewRendering2D();
3833 static const int bboxelements[36] =
3843 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3846 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3847 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3848 GL_DepthMask(false);
3849 GL_DepthRange(0, 1);
3850 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3851 R_Mesh_Matrix(&identitymatrix);
3852 R_Mesh_ResetTextureState();
3854 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3855 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3856 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3857 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3858 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3859 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3860 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3861 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3862 R_FillColors(color4f, 8, cr, cg, cb, ca);
3863 if (r_refdef.fogenabled)
3865 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3867 f1 = FogPoint_World(v);
3869 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3870 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3871 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3874 R_Mesh_VertexPointer(vertex3f, 0, 0);
3875 R_Mesh_ColorPointer(color4f, 0, 0);
3876 R_Mesh_ResetTextureState();
3877 R_SetupGenericShader(false);
3878 R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3881 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3885 prvm_edict_t *edict;
3886 // this function draws bounding boxes of server entities
3889 R_SetupGenericShader(false);
3891 for (i = 0;i < numsurfaces;i++)
3893 edict = PRVM_EDICT_NUM(surfacelist[i]);
3894 switch ((int)edict->fields.server->solid)
3896 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
3897 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
3898 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
3899 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3900 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
3901 default: Vector4Set(color, 0, 0, 0, 0.50);break;
3903 color[3] *= r_showbboxes.value;
3904 color[3] = bound(0, color[3], 1);
3905 GL_DepthTest(!r_showdisabledepthtest.integer);
3906 GL_CullFace(r_refdef.view.cullface_front);
3907 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3912 static void R_DrawEntityBBoxes(void)
3915 prvm_edict_t *edict;
3917 // this function draws bounding boxes of server entities
3921 for (i = 0;i < prog->num_edicts;i++)
3923 edict = PRVM_EDICT_NUM(i);
3924 if (edict->priv.server->free)
3926 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3927 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3932 int nomodelelements[24] =
3944 float nomodelvertex3f[6*3] =
3954 float nomodelcolor4f[6*4] =
3956 0.0f, 0.0f, 0.5f, 1.0f,
3957 0.0f, 0.0f, 0.5f, 1.0f,
3958 0.0f, 0.5f, 0.0f, 1.0f,
3959 0.0f, 0.5f, 0.0f, 1.0f,
3960 0.5f, 0.0f, 0.0f, 1.0f,
3961 0.5f, 0.0f, 0.0f, 1.0f
3964 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3969 // this is only called once per entity so numsurfaces is always 1, and
3970 // surfacelist is always {0}, so this code does not handle batches
3971 R_Mesh_Matrix(&ent->matrix);
3973 if (ent->flags & EF_ADDITIVE)
3975 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3976 GL_DepthMask(false);
3978 else if (ent->alpha < 1)
3980 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3981 GL_DepthMask(false);
3985 GL_BlendFunc(GL_ONE, GL_ZERO);
3988 GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3989 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3990 GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3991 GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
3992 R_SetupGenericShader(false);
3993 R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
3994 if (r_refdef.fogenabled)
3997 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
3998 R_Mesh_ColorPointer(color4f, 0, 0);
3999 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4000 f1 = FogPoint_World(org);
4002 for (i = 0, c = color4f;i < 6;i++, c += 4)
4004 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4005 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4006 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4010 else if (ent->alpha != 1)
4012 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4013 R_Mesh_ColorPointer(color4f, 0, 0);
4014 for (i = 0, c = color4f;i < 6;i++, c += 4)
4018 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4019 R_Mesh_ResetTextureState();
4020 R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
4023 void R_DrawNoModel(entity_render_t *ent)
4026 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4027 //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4028 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4030 // R_DrawNoModelCallback(ent, 0);
4033 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4035 vec3_t right1, right2, diff, normal;
4037 VectorSubtract (org2, org1, normal);
4039 // calculate 'right' vector for start
4040 VectorSubtract (r_refdef.view.origin, org1, diff);
4041 CrossProduct (normal, diff, right1);
4042 VectorNormalize (right1);
4044 // calculate 'right' vector for end
4045 VectorSubtract (r_refdef.view.origin, org2, diff);
4046 CrossProduct (normal, diff, right2);
4047 VectorNormalize (right2);
4049 vert[ 0] = org1[0] + width * right1[0];
4050 vert[ 1] = org1[1] + width * right1[1];
4051 vert[ 2] = org1[2] + width * right1[2];
4052 vert[ 3] = org1[0] - width * right1[0];
4053 vert[ 4] = org1[1] - width * right1[1];
4054 vert[ 5] = org1[2] - width * right1[2];
4055 vert[ 6] = org2[0] - width * right2[0];
4056 vert[ 7] = org2[1] - width * right2[1];
4057 vert[ 8] = org2[2] - width * right2[2];
4058 vert[ 9] = org2[0] + width * right2[0];
4059 vert[10] = org2[1] + width * right2[1];
4060 vert[11] = org2[2] + width * right2[2];
4063 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4065 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)
4070 if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4071 fog = FogPoint_World(origin);
4073 R_Mesh_Matrix(&identitymatrix);
4074 GL_BlendFunc(blendfunc1, blendfunc2);
4080 GL_CullFace(r_refdef.view.cullface_front);
4083 GL_CullFace(r_refdef.view.cullface_back);
4084 GL_CullFace(GL_NONE);
4086 GL_DepthMask(false);
4087 GL_DepthRange(0, depthshort ? 0.0625 : 1);
4088 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4089 GL_DepthTest(!depthdisable);
4091 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4092 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4093 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4094 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4095 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4096 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4097 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4098 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4099 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4100 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4101 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4102 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4104 R_Mesh_VertexPointer(vertex3f, 0, 0);
4105 R_Mesh_ColorPointer(NULL, 0, 0);
4106 R_Mesh_ResetTextureState();
4107 R_SetupGenericShader(true);
4108 R_Mesh_TexBind(0, R_GetTexture(texture));
4109 R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4110 // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4111 GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4112 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4114 if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4116 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4117 GL_BlendFunc(blendfunc1, GL_ONE);
4119 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4120 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4124 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4129 VectorSet(v, x, y, z);
4130 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4131 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4133 if (i == mesh->numvertices)
4135 if (mesh->numvertices < mesh->maxvertices)
4137 VectorCopy(v, vertex3f);
4138 mesh->numvertices++;
4140 return mesh->numvertices;
4146 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4150 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4151 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4152 e = mesh->element3i + mesh->numtriangles * 3;
4153 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4155 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4156 if (mesh->numtriangles < mesh->maxtriangles)
4161 mesh->numtriangles++;
4163 element[1] = element[2];
4167 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4171 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4172 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4173 e = mesh->element3i + mesh->numtriangles * 3;
4174 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4176 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4177 if (mesh->numtriangles < mesh->maxtriangles)
4182 mesh->numtriangles++;
4184 element[1] = element[2];
4188 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4189 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4191 int planenum, planenum2;
4194 mplane_t *plane, *plane2;
4196 double temppoints[2][256*3];
4197 // figure out how large a bounding box we need to properly compute this brush
4199 for (w = 0;w < numplanes;w++)
4200 maxdist = max(maxdist, planes[w].dist);
4201 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4202 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4203 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4207 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4208 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4210 if (planenum2 == planenum)
4212 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);
4215 if (tempnumpoints < 3)
4217 // generate elements forming a triangle fan for this polygon
4218 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4222 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)
4224 texturelayer_t *layer;
4225 layer = t->currentlayers + t->currentnumlayers++;
4227 layer->depthmask = depthmask;
4228 layer->blendfunc1 = blendfunc1;
4229 layer->blendfunc2 = blendfunc2;
4230 layer->texture = texture;
4231 layer->texmatrix = *matrix;
4232 layer->color[0] = r * r_refdef.view.colorscale;
4233 layer->color[1] = g * r_refdef.view.colorscale;
4234 layer->color[2] = b * r_refdef.view.colorscale;
4235 layer->color[3] = a;
4238 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4241 index = parms[2] + r_refdef.scene.time * parms[3];
4242 index -= floor(index);
4246 case Q3WAVEFUNC_NONE:
4247 case Q3WAVEFUNC_NOISE:
4248 case Q3WAVEFUNC_COUNT:
4251 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4252 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4253 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4254 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4255 case Q3WAVEFUNC_TRIANGLE:
4257 f = index - floor(index);
4268 return (float)(parms[0] + parms[1] * f);
4271 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4274 model_t *model = ent->model;
4277 q3shaderinfo_layer_tcmod_t *tcmod;
4279 // switch to an alternate material if this is a q1bsp animated material
4281 texture_t *texture = t;
4282 int s = ent->skinnum;
4283 if ((unsigned int)s >= (unsigned int)model->numskins)
4285 if (model->skinscenes)
4287 if (model->skinscenes[s].framecount > 1)
4288 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4290 s = model->skinscenes[s].firstframe;
4293 t = t + s * model->num_surfaces;
4296 // use an alternate animation if the entity's frame is not 0,
4297 // and only if the texture has an alternate animation
4298 if (ent->frame2 != 0 && t->anim_total[1])
4299 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4301 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4303 texture->currentframe = t;
4306 // update currentskinframe to be a qw skin or animation frame
4307 if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4309 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4311 strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4312 Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4313 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);
4315 t->currentskinframe = r_qwskincache_skinframe[i];
4316 if (t->currentskinframe == NULL)
4317 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4319 else if (t->numskinframes >= 2)
4320 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4321 if (t->backgroundnumskinframes >= 2)
4322 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4324 t->currentmaterialflags = t->basematerialflags;
4325 t->currentalpha = ent->alpha;
4326 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4328 t->currentalpha *= r_wateralpha.value;
4330 * FIXME what is this supposed to do?
4331 // if rendering refraction/reflection, disable transparency
4332 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4333 t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4336 if(!r_waterstate.enabled)
4337 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4338 if (!(ent->flags & RENDER_LIGHT))
4339 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4340 else if (rsurface.modeltexcoordlightmap2f == NULL)
4342 // pick a model lighting mode
4343 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4344 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4346 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4348 if (ent->effects & EF_ADDITIVE)
4349 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4350 else if (t->currentalpha < 1)
4351 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4352 if (ent->effects & EF_DOUBLESIDED)
4353 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4354 if (ent->effects & EF_NODEPTHTEST)
4355 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4356 if (ent->flags & RENDER_VIEWMODEL)
4357 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4358 if (t->backgroundnumskinframes)
4359 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4360 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4362 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4363 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4366 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4368 // there is no tcmod
4369 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4370 t->currenttexmatrix = r_waterscrollmatrix;
4372 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4375 switch(tcmod->tcmod)
4379 if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4380 matrix = r_waterscrollmatrix;
4382 matrix = identitymatrix;
4384 case Q3TCMOD_ENTITYTRANSLATE:
4385 // this is used in Q3 to allow the gamecode to control texcoord
4386 // scrolling on the entity, which is not supported in darkplaces yet.
4387 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4389 case Q3TCMOD_ROTATE:
4390 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4391 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4392 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4395 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4397 case Q3TCMOD_SCROLL:
4398 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4400 case Q3TCMOD_STRETCH:
4401 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4402 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4404 case Q3TCMOD_TRANSFORM:
4405 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
4406 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
4407 VectorSet(tcmat + 6, 0 , 0 , 1);
4408 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
4409 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4411 case Q3TCMOD_TURBULENT:
4412 // this is handled in the RSurf_PrepareVertices function
4413 matrix = identitymatrix;
4416 // either replace or concatenate the transformation
4418 t->currenttexmatrix = matrix;
4421 matrix4x4_t temp = t->currenttexmatrix;
4422 Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4426 t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4427 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4428 t->glosstexture = r_texture_black;
4429 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4430 t->backgroundglosstexture = r_texture_black;
4431 t->specularpower = r_shadow_glossexponent.value;
4432 // TODO: store reference values for these in the texture?
4433 t->specularscale = 0;
4434 if (r_shadow_gloss.integer > 0)
4436 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4438 if (r_shadow_glossintensity.value > 0)
4440 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4441 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4442 t->specularscale = r_shadow_glossintensity.value;
4445 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4447 t->glosstexture = r_texture_white;
4448 t->backgroundglosstexture = r_texture_white;
4449 t->specularscale = r_shadow_gloss2intensity.value;
4453 // lightmaps mode looks bad with dlights using actual texturing, so turn
4454 // off the colormap and glossmap, but leave the normalmap on as it still
4455 // accurately represents the shading involved
4456 if (gl_lightmaps.integer && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
4458 t->basetexture = r_texture_white;
4459 t->specularscale = 0;
4462 Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4463 VectorClear(t->dlightcolor);
4464 t->currentnumlayers = 0;
4465 if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4467 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4469 int blendfunc1, blendfunc2, depthmask;
4470 if (t->currentmaterialflags & MATERIALFLAG_ADD)
4472 blendfunc1 = GL_SRC_ALPHA;
4473 blendfunc2 = GL_ONE;
4475 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4477 blendfunc1 = GL_SRC_ALPHA;
4478 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4480 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4482 blendfunc1 = t->customblendfunc[0];
4483 blendfunc2 = t->customblendfunc[1];
4487 blendfunc1 = GL_ONE;
4488 blendfunc2 = GL_ZERO;
4490 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4491 if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4493 rtexture_t *currentbasetexture;
4495 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4496 layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4497 currentbasetexture = (VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) < (1.0f / 1048576.0f) && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4498 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4500 // fullbright is not affected by r_refdef.lightmapintensity
4501 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4502 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4503 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]);
4504 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4505 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]);
4509 vec3_t ambientcolor;
4511 // set the color tint used for lights affecting this surface
4512 VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4514 // q3bsp has no lightmap updates, so the lightstylevalue that
4515 // would normally be baked into the lightmap must be
4516 // applied to the color
4517 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4518 if (ent->model->type == mod_brushq3)
4519 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4520 colorscale *= r_refdef.lightmapintensity;
4521 VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4522 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4523 // basic lit geometry
4524 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, currentbasetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4525 // add pants/shirt if needed
4526 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4527 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]);
4528 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4529 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]);
4530 // now add ambient passes if needed
4531 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4533 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, currentbasetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4534 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4535 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]);
4536 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4537 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]);
4540 if (t->currentskinframe->glow != NULL)
4541 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]);
4542 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4544 // if this is opaque use alpha blend which will darken the earlier
4547 // if this is an alpha blended material, all the earlier passes
4548 // were darkened by fog already, so we only need to add the fog
4549 // color ontop through the fog mask texture
4551 // if this is an additive blended material, all the earlier passes
4552 // were darkened by fog already, and we should not add fog color
4553 // (because the background was not darkened, there is no fog color
4554 // that was lost behind it).
4555 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]);
4562 void R_UpdateAllTextureInfo(entity_render_t *ent)
4566 for (i = 0;i < ent->model->num_texturesperskin;i++)
4567 R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4570 rsurfacestate_t rsurface;
4572 void R_Mesh_ResizeArrays(int newvertices)
4575 if (rsurface.array_size >= newvertices)
4577 if (rsurface.array_modelvertex3f)
4578 Mem_Free(rsurface.array_modelvertex3f);
4579 rsurface.array_size = (newvertices + 1023) & ~1023;
4580 base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4581 rsurface.array_modelvertex3f = base + rsurface.array_size * 0;
4582 rsurface.array_modelsvector3f = base + rsurface.array_size * 3;
4583 rsurface.array_modeltvector3f = base + rsurface.array_size * 6;
4584 rsurface.array_modelnormal3f = base + rsurface.array_size * 9;
4585 rsurface.array_deformedvertex3f = base + rsurface.array_size * 12;
4586 rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4587 rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4588 rsurface.array_deformednormal3f = base + rsurface.array_size * 21;
4589 rsurface.array_texcoord3f = base + rsurface.array_size * 24;
4590 rsurface.array_color4f = base + rsurface.array_size * 27;
4591 rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4594 void RSurf_CleanUp(void)
4597 GL_AlphaTest(false);
4598 rsurface.mode = RSURFMODE_NONE;
4599 rsurface.uselightmaptexture = false;
4600 rsurface.texture = NULL;
4603 void RSurf_ActiveWorldEntity(void)
4605 model_t *model = r_refdef.scene.worldmodel;
4607 if (rsurface.array_size < model->surfmesh.num_vertices)
4608 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4609 rsurface.matrix = identitymatrix;
4610 rsurface.inversematrix = identitymatrix;
4611 R_Mesh_Matrix(&identitymatrix);
4612 VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4613 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4614 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4615 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4616 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4617 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4618 rsurface.frameblend[0].frame = 0;
4619 rsurface.frameblend[0].lerp = 1;
4620 rsurface.frameblend[1].frame = 0;
4621 rsurface.frameblend[1].lerp = 0;
4622 rsurface.frameblend[2].frame = 0;
4623 rsurface.frameblend[2].lerp = 0;
4624 rsurface.frameblend[3].frame = 0;
4625 rsurface.frameblend[3].lerp = 0;
4626 rsurface.basepolygonfactor = r_refdef.polygonfactor;
4627 rsurface.basepolygonoffset = r_refdef.polygonoffset;
4628 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
4629 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4630 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4631 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4632 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4633 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4634 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4635 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4636 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4637 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
4638 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4639 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4640 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
4641 rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4642 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4643 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
4644 rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4645 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4646 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
4647 rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4648 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4649 rsurface.modelelement3i = model->surfmesh.data_element3i;
4650 rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4651 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4652 rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4653 rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4654 rsurface.modelsurfaces = model->data_surfaces;
4655 rsurface.generatedvertex = false;
4656 rsurface.vertex3f = rsurface.modelvertex3f;
4657 rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4658 rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4659 rsurface.svector3f = rsurface.modelsvector3f;
4660 rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4661 rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4662 rsurface.tvector3f = rsurface.modeltvector3f;
4663 rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4664 rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4665 rsurface.normal3f = rsurface.modelnormal3f;
4666 rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4667 rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4668 rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4671 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4673 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_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5698 RSurf_SetupDepthAndCulling();
5699 if (rsurface.mode != RSURFMODE_SHOWSURFACES)
5701 rsurface.mode = RSURFMODE_SHOWSURFACES;
5703 GL_BlendFunc(GL_ONE, GL_ZERO);
5704 R_Mesh_ColorPointer(NULL, 0, 0);
5705 R_Mesh_ResetTextureState();
5707 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5708 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
5711 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5713 // transparent sky would be ridiculous
5714 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5716 if (rsurface.mode != RSURFMODE_SKY)
5718 if (rsurface.mode == RSURFMODE_GLSL)
5719 R_SetupGenericShader(false);
5720 rsurface.mode = RSURFMODE_SKY;
5724 skyrendernow = false;
5725 // we have to force off the water clipping plane while rendering sky
5729 // restore entity matrix
5730 R_Mesh_Matrix(&rsurface.matrix);
5732 RSurf_SetupDepthAndCulling();
5734 // LordHavoc: HalfLife maps have freaky skypolys so don't use
5735 // skymasking on them, and Quake3 never did sky masking (unlike
5736 // software Quake and software Quake2), so disable the sky masking
5737 // in Quake3 maps as it causes problems with q3map2 sky tricks,
5738 // and skymasking also looks very bad when noclipping outside the
5739 // level, so don't use it then either.
5740 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5742 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5743 R_Mesh_ColorPointer(NULL, 0, 0);
5744 R_Mesh_ResetTextureState();
5745 if (skyrendermasked)
5747 R_SetupDepthOrShadowShader();
5748 // depth-only (masking)
5749 GL_ColorMask(0,0,0,0);
5750 // just to make sure that braindead drivers don't draw
5751 // anything despite that colormask...
5752 GL_BlendFunc(GL_ZERO, GL_ONE);
5756 R_SetupGenericShader(false);
5758 GL_BlendFunc(GL_ONE, GL_ZERO);
5760 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5761 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5762 if (skyrendermasked)
5763 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5767 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
5769 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5772 if (rsurface.mode != RSURFMODE_GLSL)
5774 rsurface.mode = RSURFMODE_GLSL;
5775 R_Mesh_ResetTextureState();
5776 GL_Color(1, 1, 1, 1);
5779 R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5780 R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5781 R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
5782 R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
5783 R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
5784 if (rsurface.texture->backgroundcurrentskinframe)
5786 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
5787 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
5788 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
5789 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
5791 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
5792 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5793 R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
5794 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5795 R_Mesh_ColorPointer(NULL, 0, 0);
5797 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5799 if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5801 // render background
5802 GL_BlendFunc(GL_ONE, GL_ZERO);
5804 GL_AlphaTest(false);
5806 GL_Color(1, 1, 1, 1);
5807 R_Mesh_ColorPointer(NULL, 0, 0);
5809 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5810 if (r_glsl_permutation)
5812 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5813 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5814 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5815 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5816 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5817 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5818 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);
5821 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5822 GL_DepthMask(false);
5823 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5824 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5825 R_Mesh_ColorPointer(NULL, 0, 0);
5827 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5828 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
5829 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
5832 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5833 if (!r_glsl_permutation)
5836 RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5837 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5838 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5839 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5840 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5841 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5843 if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5845 GL_BlendFunc(GL_ONE, GL_ZERO);
5847 GL_AlphaTest(false);
5850 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5852 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5853 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);
5855 RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
5859 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5860 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);
5862 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5866 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
5868 // OpenGL 1.3 path - anything not completely ancient
5869 int texturesurfaceindex;
5870 qboolean applycolor;
5874 const texturelayer_t *layer;
5875 if (rsurface.mode != RSURFMODE_MULTIPASS)
5876 rsurface.mode = RSURFMODE_MULTIPASS;
5877 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5879 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5882 int layertexrgbscale;
5883 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5885 if (layerindex == 0)
5889 GL_AlphaTest(false);
5890 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5893 GL_DepthMask(layer->depthmask);
5894 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5895 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5897 layertexrgbscale = 4;
5898 VectorScale(layer->color, 0.25f, layercolor);
5900 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5902 layertexrgbscale = 2;
5903 VectorScale(layer->color, 0.5f, layercolor);
5907 layertexrgbscale = 1;
5908 VectorScale(layer->color, 1.0f, layercolor);
5910 layercolor[3] = layer->color[3];
5911 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5912 R_Mesh_ColorPointer(NULL, 0, 0);
5913 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5914 switch (layer->type)
5916 case TEXTURELAYERTYPE_LITTEXTURE:
5917 memset(&m, 0, sizeof(m));
5918 m.tex[0] = R_GetTexture(r_texture_white);
5919 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5920 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5921 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5922 m.tex[1] = R_GetTexture(layer->texture);
5923 m.texmatrix[1] = layer->texmatrix;
5924 m.texrgbscale[1] = layertexrgbscale;
5925 m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5926 m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5927 m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5928 R_Mesh_TextureState(&m);
5929 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5930 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5931 else if (rsurface.uselightmaptexture)
5932 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5934 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5936 case TEXTURELAYERTYPE_TEXTURE:
5937 memset(&m, 0, sizeof(m));
5938 m.tex[0] = R_GetTexture(layer->texture);
5939 m.texmatrix[0] = layer->texmatrix;
5940 m.texrgbscale[0] = layertexrgbscale;
5941 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5942 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5943 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5944 R_Mesh_TextureState(&m);
5945 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5947 case TEXTURELAYERTYPE_FOG:
5948 memset(&m, 0, sizeof(m));
5949 m.texrgbscale[0] = layertexrgbscale;
5952 m.tex[0] = R_GetTexture(layer->texture);
5953 m.texmatrix[0] = layer->texmatrix;
5954 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5955 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5956 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5958 R_Mesh_TextureState(&m);
5959 // generate a color array for the fog pass
5960 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5961 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5965 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5966 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)
5968 f = 1 - FogPoint_Model(v);
5969 c[0] = layercolor[0];
5970 c[1] = layercolor[1];
5971 c[2] = layercolor[2];
5972 c[3] = f * layercolor[3];
5975 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5978 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5980 GL_LockArrays(0, 0);
5983 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5985 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5986 GL_AlphaTest(false);
5990 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist)
5992 // OpenGL 1.1 - crusty old voodoo path
5993 int texturesurfaceindex;
5997 const texturelayer_t *layer;
5998 if (rsurface.mode != RSURFMODE_MULTIPASS)
5999 rsurface.mode = RSURFMODE_MULTIPASS;
6000 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
6002 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
6004 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6006 if (layerindex == 0)
6010 GL_AlphaTest(false);
6011 qglDepthFunc(GL_EQUAL);CHECKGLERROR
6014 GL_DepthMask(layer->depthmask);
6015 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
6016 R_Mesh_ColorPointer(NULL, 0, 0);
6017 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
6018 switch (layer->type)
6020 case TEXTURELAYERTYPE_LITTEXTURE:
6021 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
6023 // two-pass lit texture with 2x rgbscale
6024 // first the lightmap pass
6025 memset(&m, 0, sizeof(m));
6026 m.tex[0] = R_GetTexture(r_texture_white);
6027 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6028 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6029 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6030 R_Mesh_TextureState(&m);
6031 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6032 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6033 else if (rsurface.uselightmaptexture)
6034 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6036 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6037 GL_LockArrays(0, 0);
6038 // then apply the texture to it
6039 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6040 memset(&m, 0, sizeof(m));
6041 m.tex[0] = R_GetTexture(layer->texture);
6042 m.texmatrix[0] = layer->texmatrix;
6043 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6044 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6045 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6046 R_Mesh_TextureState(&m);
6047 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);
6051 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6052 memset(&m, 0, sizeof(m));
6053 m.tex[0] = R_GetTexture(layer->texture);
6054 m.texmatrix[0] = layer->texmatrix;
6055 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6056 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6057 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6058 R_Mesh_TextureState(&m);
6059 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6060 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);
6062 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);
6065 case TEXTURELAYERTYPE_TEXTURE:
6066 // singletexture unlit texture with transparency support
6067 memset(&m, 0, sizeof(m));
6068 m.tex[0] = R_GetTexture(layer->texture);
6069 m.texmatrix[0] = layer->texmatrix;
6070 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6071 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6072 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6073 R_Mesh_TextureState(&m);
6074 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);
6076 case TEXTURELAYERTYPE_FOG:
6077 // singletexture fogging
6078 R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6081 memset(&m, 0, sizeof(m));
6082 m.tex[0] = R_GetTexture(layer->texture);
6083 m.texmatrix[0] = layer->texmatrix;
6084 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6085 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6086 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6087 R_Mesh_TextureState(&m);
6090 R_Mesh_ResetTextureState();
6091 // generate a color array for the fog pass
6092 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6096 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6097 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)
6099 f = 1 - FogPoint_Model(v);
6100 c[0] = layer->color[0];
6101 c[1] = layer->color[1];
6102 c[2] = layer->color[2];
6103 c[3] = f * layer->color[3];
6106 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6109 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6111 GL_LockArrays(0, 0);
6114 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6116 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6117 GL_AlphaTest(false);
6121 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
6123 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW)
6125 rsurface.rtlight = NULL;
6129 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6131 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6133 if (rsurface.mode != RSURFMODE_MULTIPASS)
6134 rsurface.mode = RSURFMODE_MULTIPASS;
6135 if (r_depthfirst.integer == 3)
6137 int i = (int)(texturesurfacelist[0] - rsurface.modelsurfaces);
6138 if (!r_refdef.view.showdebug)
6139 GL_Color(0, 0, 0, 1);
6141 GL_Color(((i >> 6) & 7) / 7.0f, ((i >> 3) & 7) / 7.0f, (i & 7) / 7.0f,1);
6145 GL_ColorMask(0,0,0,0);
6148 RSurf_SetupDepthAndCulling();
6150 GL_BlendFunc(GL_ONE, GL_ZERO);
6152 GL_AlphaTest(false);
6153 R_Mesh_ColorPointer(NULL, 0, 0);
6154 R_Mesh_ResetTextureState();
6155 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6156 R_SetupDepthOrShadowShader();
6157 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6158 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6160 else if (r_depthfirst.integer == 3)
6162 else if (!r_refdef.view.showdebug && (r_showsurfaces.integer || gl_lightmaps.integer))
6164 GL_Color(0, 0, 0, 1);
6165 R_SetupGenericShader(false);
6166 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6168 else if (r_showsurfaces.integer)
6170 if (rsurface.mode != RSURFMODE_MULTIPASS)
6171 rsurface.mode = RSURFMODE_MULTIPASS;
6172 RSurf_SetupDepthAndCulling();
6174 GL_BlendFunc(GL_ONE, GL_ZERO);
6175 GL_DepthMask(writedepth);
6177 GL_AlphaTest(false);
6178 R_Mesh_ColorPointer(NULL, 0, 0);
6179 R_Mesh_ResetTextureState();
6180 R_SetupGenericShader(false);
6181 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6182 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6184 else if (gl_lightmaps.integer)
6187 if (rsurface.mode != RSURFMODE_MULTIPASS)
6188 rsurface.mode = RSURFMODE_MULTIPASS;
6189 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
6191 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
6192 GL_BlendFunc(GL_ONE, GL_ZERO);
6193 GL_DepthMask(writedepth);
6195 GL_AlphaTest(false);
6196 R_Mesh_ColorPointer(NULL, 0, 0);
6197 R_SetupGenericShader(true);
6198 memset(&m, 0, sizeof(m));
6199 m.tex[0] = R_GetTexture(r_texture_white);
6200 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6201 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6202 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6203 R_Mesh_TextureState(&m);
6204 RSurf_PrepareVerticesForBatch(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, false, texturenumsurfaces, texturesurfacelist);
6205 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6206 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6207 else if (rsurface.uselightmaptexture)
6208 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6210 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6212 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6213 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6214 else if (rsurface.texture->currentnumlayers)
6216 // write depth for anything we skipped on the depth-only pass earlier
6217 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6219 RSurf_SetupDepthAndCulling();
6220 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
6221 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
6222 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
6223 if (r_glsl.integer && gl_support_fragment_shader)
6224 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist);
6225 else if (gl_combine.integer && r_textureunits.integer >= 2)
6226 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist);
6228 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist);
6231 GL_LockArrays(0, 0);
6234 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6237 int texturenumsurfaces, endsurface;
6239 msurface_t *surface;
6240 msurface_t *texturesurfacelist[1024];
6242 // if the model is static it doesn't matter what value we give for
6243 // wantnormals and wanttangents, so this logic uses only rules applicable
6244 // to a model, knowing that they are meaningless otherwise
6245 if (ent == r_refdef.scene.worldentity)
6246 RSurf_ActiveWorldEntity();
6247 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6248 RSurf_ActiveModelEntity(ent, false, false);
6250 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6252 for (i = 0;i < numsurfaces;i = j)
6255 surface = rsurface.modelsurfaces + surfacelist[i];
6256 texture = surface->texture;
6257 R_UpdateTextureInfo(ent, texture);
6258 rsurface.texture = texture->currentframe;
6259 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6260 // scan ahead until we find a different texture
6261 endsurface = min(i + 1024, numsurfaces);
6262 texturenumsurfaces = 0;
6263 texturesurfacelist[texturenumsurfaces++] = surface;
6264 for (;j < endsurface;j++)
6266 surface = rsurface.modelsurfaces + surfacelist[j];
6267 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6269 texturesurfacelist[texturenumsurfaces++] = surface;
6271 // render the range of surfaces
6272 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, true, false);
6278 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6281 vec3_t tempcenter, center;
6283 // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6286 for (i = 0;i < numsurfaces;i++)
6287 if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6288 R_Water_AddWaterPlane(surfacelist[i]);
6291 // break the surface list down into batches by texture and use of lightmapping
6292 for (i = 0;i < numsurfaces;i = j)
6295 // texture is the base texture pointer, rsurface.texture is the
6296 // current frame/skin the texture is directing us to use (for example
6297 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6298 // use skin 1 instead)
6299 texture = surfacelist[i]->texture;
6300 rsurface.texture = texture->currentframe;
6301 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6302 if (!(rsurface.texture->currentmaterialflags & flagsmask))
6304 // if this texture is not the kind we want, skip ahead to the next one
6305 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6309 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
6311 // transparent surfaces get pushed off into the transparent queue
6312 const msurface_t *surface = surfacelist[i];
6315 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6316 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6317 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6318 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6319 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, ent, surface - rsurface.modelsurfaces, rsurface.rtlight);
6323 // simply scan ahead until we find a different texture or lightmap state
6324 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6326 // render the range of surfaces
6327 R_DrawTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
6332 float locboxvertex3f[6*4*3] =
6334 1,0,1, 1,0,0, 1,1,0, 1,1,1,
6335 0,1,1, 0,1,0, 0,0,0, 0,0,1,
6336 1,1,1, 1,1,0, 0,1,0, 0,1,1,
6337 0,0,1, 0,0,0, 1,0,0, 1,0,1,
6338 0,0,1, 1,0,1, 1,1,1, 0,1,1,
6339 1,0,0, 0,0,0, 0,1,0, 1,1,0
6342 int locboxelement3i[6*2*3] =
6352 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6355 cl_locnode_t *loc = (cl_locnode_t *)ent;
6357 float vertex3f[6*4*3];
6359 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6360 GL_DepthMask(false);
6361 GL_DepthRange(0, 1);
6362 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6364 GL_CullFace(GL_NONE);
6365 R_Mesh_Matrix(&identitymatrix);
6367 R_Mesh_VertexPointer(vertex3f, 0, 0);
6368 R_Mesh_ColorPointer(NULL, 0, 0);
6369 R_Mesh_ResetTextureState();
6370 R_SetupGenericShader(false);
6373 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6374 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6375 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6376 surfacelist[0] < 0 ? 0.5f : 0.125f);
6378 if (VectorCompare(loc->mins, loc->maxs))
6380 VectorSet(size, 2, 2, 2);
6381 VectorMA(loc->mins, -0.5f, size, mins);
6385 VectorCopy(loc->mins, mins);
6386 VectorSubtract(loc->maxs, loc->mins, size);
6389 for (i = 0;i < 6*4*3;)
6390 for (j = 0;j < 3;j++, i++)
6391 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6393 R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6396 void R_DrawLocs(void)
6399 cl_locnode_t *loc, *nearestloc;
6401 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6402 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6404 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6405 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6409 void R_DrawDebugModel(entity_render_t *ent)
6411 int i, j, k, l, flagsmask;
6412 const int *elements;
6414 msurface_t *surface;
6415 model_t *model = ent->model;
6418 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6420 R_Mesh_ColorPointer(NULL, 0, 0);
6421 R_Mesh_ResetTextureState();
6422 R_SetupGenericShader(false);
6423 GL_DepthRange(0, 1);
6424 GL_DepthTest(!r_showdisabledepthtest.integer);
6425 GL_DepthMask(false);
6426 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6428 if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6430 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6431 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6433 if (brush->colbrushf && brush->colbrushf->numtriangles)
6435 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6436 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);
6437 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6440 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6442 if (surface->num_collisiontriangles)
6444 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6445 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);
6446 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6451 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6453 if (r_showtris.integer || r_shownormals.integer)
6455 if (r_showdisabledepthtest.integer)
6457 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6458 GL_DepthMask(false);
6462 GL_BlendFunc(GL_ONE, GL_ZERO);
6465 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6467 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6469 rsurface.texture = surface->texture->currentframe;
6470 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6472 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6473 if (r_showtris.value > 0)
6475 if (!rsurface.texture->currentlayers->depthmask)
6476 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6477 else if (ent == r_refdef.scene.worldentity)
6478 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6480 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6481 elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6484 for (k = 0;k < surface->num_triangles;k++, elements += 3)
6486 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6487 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6488 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6489 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6494 if (r_shownormals.value > 0)
6497 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6499 VectorCopy(rsurface.vertex3f + l * 3, v);
6500 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6501 qglVertex3f(v[0], v[1], v[2]);
6502 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6503 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6504 qglVertex3f(v[0], v[1], v[2]);
6509 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6511 VectorCopy(rsurface.vertex3f + l * 3, v);
6512 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6513 qglVertex3f(v[0], v[1], v[2]);
6514 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6515 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6516 qglVertex3f(v[0], v[1], v[2]);
6521 for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6523 VectorCopy(rsurface.vertex3f + l * 3, v);
6524 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6525 qglVertex3f(v[0], v[1], v[2]);
6526 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6527 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6528 qglVertex3f(v[0], v[1], v[2]);
6535 rsurface.texture = NULL;
6539 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6540 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6542 int i, j, endj, f, flagsmask;
6543 msurface_t *surface;
6545 model_t *model = r_refdef.scene.worldmodel;
6546 const int maxsurfacelist = 1024;
6547 int numsurfacelist = 0;
6548 msurface_t *surfacelist[1024];
6552 RSurf_ActiveWorldEntity();
6554 // update light styles on this submodel
6555 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6557 model_brush_lightstyleinfo_t *style;
6558 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6560 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6562 msurface_t *surfaces = model->data_surfaces;
6563 int *list = style->surfacelist;
6564 style->value = r_refdef.scene.lightstylevalue[style->style];
6565 for (j = 0;j < style->numsurfaces;j++)
6566 surfaces[list[j]].cached_dlight = true;
6571 R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6572 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6576 R_DrawDebugModel(r_refdef.scene.worldentity);
6582 rsurface.uselightmaptexture = false;
6583 rsurface.texture = NULL;
6585 j = model->firstmodelsurface;
6586 endj = j + model->nummodelsurfaces;
6589 // quickly skip over non-visible surfaces
6590 for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
6592 // quickly iterate over visible surfaces
6593 for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
6595 // process this surface
6596 surface = model->data_surfaces + j;
6597 // if this surface fits the criteria, add it to the list
6598 if (surface->num_triangles)
6600 // if lightmap parameters changed, rebuild lightmap texture
6601 if (surface->cached_dlight)
6602 R_BuildLightMap(r_refdef.scene.worldentity, surface);
6603 // add face to draw list
6604 surfacelist[numsurfacelist++] = surface;
6605 r_refdef.stats.world_triangles += surface->num_triangles;
6606 if (numsurfacelist >= maxsurfacelist)
6608 r_refdef.stats.world_surfaces += numsurfacelist;
6609 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6615 r_refdef.stats.world_surfaces += numsurfacelist;
6617 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6621 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6623 int i, j, f, flagsmask;
6624 msurface_t *surface, *endsurface;
6626 model_t *model = ent->model;
6627 const int maxsurfacelist = 1024;
6628 int numsurfacelist = 0;
6629 msurface_t *surfacelist[1024];
6633 // if the model is static it doesn't matter what value we give for
6634 // wantnormals and wanttangents, so this logic uses only rules applicable
6635 // to a model, knowing that they are meaningless otherwise
6636 if (ent == r_refdef.scene.worldentity)
6637 RSurf_ActiveWorldEntity();
6638 else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6639 RSurf_ActiveModelEntity(ent, false, false);
6641 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6643 // update light styles
6644 if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6646 model_brush_lightstyleinfo_t *style;
6647 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6649 if (style->value != r_refdef.scene.lightstylevalue[style->style])
6651 msurface_t *surfaces = model->data_surfaces;
6652 int *list = style->surfacelist;
6653 style->value = r_refdef.scene.lightstylevalue[style->style];
6654 for (j = 0;j < style->numsurfaces;j++)
6655 surfaces[list[j]].cached_dlight = true;
6660 R_UpdateAllTextureInfo(ent);
6661 flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6665 R_DrawDebugModel(ent);
6671 rsurface.uselightmaptexture = false;
6672 rsurface.texture = NULL;
6674 surface = model->data_surfaces + model->firstmodelsurface;
6675 endsurface = surface + model->nummodelsurfaces;
6676 for (;surface < endsurface;surface++)
6678 // if this surface fits the criteria, add it to the list
6679 if (surface->num_triangles)
6681 // if lightmap parameters changed, rebuild lightmap texture
6682 if (surface->cached_dlight)
6683 R_BuildLightMap(ent, surface);
6684 // add face to draw list
6685 surfacelist[numsurfacelist++] = surface;
6686 r_refdef.stats.entities_triangles += surface->num_triangles;
6687 if (numsurfacelist >= maxsurfacelist)
6689 r_refdef.stats.entities_surfaces += numsurfacelist;
6690 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6695 r_refdef.stats.entities_surfaces += numsurfacelist;
6697 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);