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.
29 #include "dpsoftrast.h"
30 #include "cl_collision.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
65 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
66 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
72 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
73 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
74 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
75 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
76 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
81 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
84 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
92 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
93 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
96 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%, 10 = 100%)" };
97 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)"};
98 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
99 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
100 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"};
101 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"};
102 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
103 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"};
104 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"};
105 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"};
106 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
107 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
108 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
109 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
110 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
111 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
112 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
113 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
114 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
115 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
116 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
117 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
118 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
119 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
120 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
121 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
123 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
124 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
125 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
127 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
128 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
129 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
131 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
133 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
134 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
135 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
136 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
137 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
138 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
139 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
140 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
141 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
142 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
143 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
144 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
145 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
146 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"};
147 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
148 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
149 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
151 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
152 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
153 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
154 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
155 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
156 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
157 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
158 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
160 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
161 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
162 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
163 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
164 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
165 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
166 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
167 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
169 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
170 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
172 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
173 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
174 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
176 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
177 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
178 cvar_t r_rendertarget_debug = {0, "r_rendertarget_debug", "-1", "replaces the view with the contents of the specified render target (by number - note that these can fluctuate depending on scene)"};
179 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
180 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
181 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
182 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
183 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
184 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
185 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
187 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
188 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)"};
189 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
190 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
191 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
192 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
193 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
194 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
195 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
196 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
197 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
198 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
199 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
200 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
201 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
202 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
203 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
204 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
205 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
207 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)"};
208 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
209 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
210 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"};
211 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
212 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
213 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
214 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
215 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
217 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
218 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
219 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
220 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
222 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
223 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
225 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
226 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
227 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
228 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
229 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
230 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
232 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
233 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
234 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
235 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
236 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
237 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
239 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
240 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
241 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
243 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"};
245 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"};
247 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
249 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
251 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
252 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
253 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
254 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
256 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
257 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
259 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
261 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
262 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
264 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
265 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
266 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
267 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
270 extern cvar_t v_glslgamma_2d;
272 extern qboolean v_flipped_state;
274 r_framebufferstate_t r_fb;
276 /// shadow volume bsp struct with automatically growing nodes buffer
279 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
281 rtexture_t *r_texture_blanknormalmap;
282 rtexture_t *r_texture_white;
283 rtexture_t *r_texture_grey128;
284 rtexture_t *r_texture_black;
285 rtexture_t *r_texture_notexture;
286 rtexture_t *r_texture_whitecube;
287 rtexture_t *r_texture_normalizationcube;
288 rtexture_t *r_texture_fogattenuation;
289 rtexture_t *r_texture_fogheighttexture;
290 rtexture_t *r_texture_gammaramps;
291 unsigned int r_texture_gammaramps_serial;
292 //rtexture_t *r_texture_fogintensity;
293 rtexture_t *r_texture_reflectcube;
295 // TODO: hash lookups?
296 typedef struct cubemapinfo_s
303 int r_texture_numcubemaps;
304 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
306 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
307 unsigned int r_numqueries;
308 unsigned int r_maxqueries;
310 typedef struct r_qwskincache_s
312 char name[MAX_QPATH];
313 skinframe_t *skinframe;
317 static r_qwskincache_t *r_qwskincache;
318 static int r_qwskincache_size;
320 /// vertex coordinates for a quad that covers the screen exactly
321 extern const float r_screenvertex3f[12];
322 const float r_screenvertex3f[12] =
330 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
333 for (i = 0;i < verts;i++)
344 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
347 for (i = 0;i < verts;i++)
357 // FIXME: move this to client?
360 if (gamemode == GAME_NEHAHRA)
362 Cvar_Set("gl_fogenable", "0");
363 Cvar_Set("gl_fogdensity", "0.2");
364 Cvar_Set("gl_fogred", "0.3");
365 Cvar_Set("gl_foggreen", "0.3");
366 Cvar_Set("gl_fogblue", "0.3");
368 r_refdef.fog_density = 0;
369 r_refdef.fog_red = 0;
370 r_refdef.fog_green = 0;
371 r_refdef.fog_blue = 0;
372 r_refdef.fog_alpha = 1;
373 r_refdef.fog_start = 0;
374 r_refdef.fog_end = 16384;
375 r_refdef.fog_height = 1<<30;
376 r_refdef.fog_fadedepth = 128;
377 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
380 static void R_BuildBlankTextures(void)
382 unsigned char data[4];
383 data[2] = 128; // normal X
384 data[1] = 128; // normal Y
385 data[0] = 255; // normal Z
386 data[3] = 255; // height
387 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
402 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
405 static void R_BuildNoTexture(void)
408 unsigned char pix[16][16][4];
409 // this makes a light grey/dark grey checkerboard texture
410 for (y = 0;y < 16;y++)
412 for (x = 0;x < 16;x++)
414 if ((y < 8) ^ (x < 8))
430 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
433 static void R_BuildWhiteCube(void)
435 unsigned char data[6*1*1*4];
436 memset(data, 255, sizeof(data));
437 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
440 static void R_BuildNormalizationCube(void)
444 vec_t s, t, intensity;
447 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
448 for (side = 0;side < 6;side++)
450 for (y = 0;y < NORMSIZE;y++)
452 for (x = 0;x < NORMSIZE;x++)
454 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
455 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
490 intensity = 127.0f / sqrt(DotProduct(v, v));
491 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
492 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
493 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
494 data[((side*64+y)*64+x)*4+3] = 255;
498 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
502 static void R_BuildFogTexture(void)
506 unsigned char data1[FOGWIDTH][4];
507 //unsigned char data2[FOGWIDTH][4];
510 r_refdef.fogmasktable_start = r_refdef.fog_start;
511 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
512 r_refdef.fogmasktable_range = r_refdef.fogrange;
513 r_refdef.fogmasktable_density = r_refdef.fog_density;
515 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
516 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
518 d = (x * r - r_refdef.fogmasktable_start);
519 if(developer_extra.integer)
520 Con_DPrintf("%f ", d);
522 if (r_fog_exp2.integer)
523 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
525 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
526 if(developer_extra.integer)
527 Con_DPrintf(" : %f ", alpha);
528 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
529 if(developer_extra.integer)
530 Con_DPrintf(" = %f\n", alpha);
531 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
534 for (x = 0;x < FOGWIDTH;x++)
536 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
541 //data2[x][0] = 255 - b;
542 //data2[x][1] = 255 - b;
543 //data2[x][2] = 255 - b;
546 if (r_texture_fogattenuation)
548 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
553 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
554 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
558 static void R_BuildFogHeightTexture(void)
560 unsigned char *inpixels;
568 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
569 if (r_refdef.fogheighttexturename[0])
570 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
573 r_refdef.fog_height_tablesize = 0;
574 if (r_texture_fogheighttexture)
575 R_FreeTexture(r_texture_fogheighttexture);
576 r_texture_fogheighttexture = NULL;
577 if (r_refdef.fog_height_table2d)
578 Mem_Free(r_refdef.fog_height_table2d);
579 r_refdef.fog_height_table2d = NULL;
580 if (r_refdef.fog_height_table1d)
581 Mem_Free(r_refdef.fog_height_table1d);
582 r_refdef.fog_height_table1d = NULL;
586 r_refdef.fog_height_tablesize = size;
587 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
588 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
589 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
591 // LordHavoc: now the magic - what is that table2d for? it is a cooked
592 // average fog color table accounting for every fog layer between a point
593 // and the camera. (Note: attenuation is handled separately!)
594 for (y = 0;y < size;y++)
596 for (x = 0;x < size;x++)
602 for (j = x;j <= y;j++)
604 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
610 for (j = x;j >= y;j--)
612 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
617 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
618 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
619 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
620 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
623 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
626 //=======================================================================================================================================================
628 static const char *builtinshaderstrings[] =
630 #include "shader_glsl.h"
634 const char *builtinhlslshaderstrings[] =
636 #include "shader_hlsl.h"
640 //=======================================================================================================================================================
642 typedef struct shaderpermutationinfo_s
647 shaderpermutationinfo_t;
649 typedef struct shadermodeinfo_s
651 const char *sourcebasename;
652 const char *extension;
653 const char **builtinshaderstrings;
662 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
663 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
665 {"#define USEDIFFUSE\n", " diffuse"},
666 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
667 {"#define USEVIEWTINT\n", " viewtint"},
668 {"#define USECOLORMAPPING\n", " colormapping"},
669 {"#define USESATURATION\n", " saturation"},
670 {"#define USEFOGINSIDE\n", " foginside"},
671 {"#define USEFOGOUTSIDE\n", " fogoutside"},
672 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
673 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
674 {"#define USEGAMMARAMPS\n", " gammaramps"},
675 {"#define USECUBEFILTER\n", " cubefilter"},
676 {"#define USEGLOW\n", " glow"},
677 {"#define USEBLOOM\n", " bloom"},
678 {"#define USESPECULAR\n", " specular"},
679 {"#define USEPOSTPROCESSING\n", " postprocessing"},
680 {"#define USEREFLECTION\n", " reflection"},
681 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
682 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
683 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
684 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
685 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
686 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
687 {"#define USEALPHAKILL\n", " alphakill"},
688 {"#define USEREFLECTCUBE\n", " reflectcube"},
689 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
690 {"#define USEBOUNCEGRID\n", " bouncegrid"},
691 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
692 {"#define USETRIPPY\n", " trippy"},
693 {"#define USEDEPTHRGB\n", " depthrgb"},
694 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
695 {"#define USESKELETAL\n", " skeletal"},
696 {"#define USEOCCLUDE\n", " occlude"}
699 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
700 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
702 // SHADERLANGUAGE_GLSL
704 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
705 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
706 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
708 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
710 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
711 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
714 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
715 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
716 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
717 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
718 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
719 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
720 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
722 // SHADERLANGUAGE_HLSL
724 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
725 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
726 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
727 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
728 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
729 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
730 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
731 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
732 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
733 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
734 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
735 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
736 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
737 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
738 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
739 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
740 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
744 struct r_glsl_permutation_s;
745 typedef struct r_glsl_permutation_s
748 struct r_glsl_permutation_s *hashnext;
750 dpuint64 permutation;
752 /// indicates if we have tried compiling this permutation already
754 /// 0 if compilation failed
756 // texture units assigned to each detected uniform
757 int tex_Texture_First;
758 int tex_Texture_Second;
759 int tex_Texture_GammaRamps;
760 int tex_Texture_Normal;
761 int tex_Texture_Color;
762 int tex_Texture_Gloss;
763 int tex_Texture_Glow;
764 int tex_Texture_SecondaryNormal;
765 int tex_Texture_SecondaryColor;
766 int tex_Texture_SecondaryGloss;
767 int tex_Texture_SecondaryGlow;
768 int tex_Texture_Pants;
769 int tex_Texture_Shirt;
770 int tex_Texture_FogHeightTexture;
771 int tex_Texture_FogMask;
772 int tex_Texture_Lightmap;
773 int tex_Texture_Deluxemap;
774 int tex_Texture_Attenuation;
775 int tex_Texture_Cube;
776 int tex_Texture_Refraction;
777 int tex_Texture_Reflection;
778 int tex_Texture_ShadowMap2D;
779 int tex_Texture_CubeProjection;
780 int tex_Texture_ScreenNormalMap;
781 int tex_Texture_ScreenDiffuse;
782 int tex_Texture_ScreenSpecular;
783 int tex_Texture_ReflectMask;
784 int tex_Texture_ReflectCube;
785 int tex_Texture_BounceGrid;
786 /// locations of detected uniforms in program object, or -1 if not found
787 int loc_Texture_First;
788 int loc_Texture_Second;
789 int loc_Texture_GammaRamps;
790 int loc_Texture_Normal;
791 int loc_Texture_Color;
792 int loc_Texture_Gloss;
793 int loc_Texture_Glow;
794 int loc_Texture_SecondaryNormal;
795 int loc_Texture_SecondaryColor;
796 int loc_Texture_SecondaryGloss;
797 int loc_Texture_SecondaryGlow;
798 int loc_Texture_Pants;
799 int loc_Texture_Shirt;
800 int loc_Texture_FogHeightTexture;
801 int loc_Texture_FogMask;
802 int loc_Texture_Lightmap;
803 int loc_Texture_Deluxemap;
804 int loc_Texture_Attenuation;
805 int loc_Texture_Cube;
806 int loc_Texture_Refraction;
807 int loc_Texture_Reflection;
808 int loc_Texture_ShadowMap2D;
809 int loc_Texture_CubeProjection;
810 int loc_Texture_ScreenNormalMap;
811 int loc_Texture_ScreenDiffuse;
812 int loc_Texture_ScreenSpecular;
813 int loc_Texture_ReflectMask;
814 int loc_Texture_ReflectCube;
815 int loc_Texture_BounceGrid;
817 int loc_BloomBlur_Parameters;
819 int loc_Color_Ambient;
820 int loc_Color_Diffuse;
821 int loc_Color_Specular;
825 int loc_DeferredColor_Ambient;
826 int loc_DeferredColor_Diffuse;
827 int loc_DeferredColor_Specular;
828 int loc_DeferredMod_Diffuse;
829 int loc_DeferredMod_Specular;
830 int loc_DistortScaleRefractReflect;
833 int loc_FogHeightFade;
835 int loc_FogPlaneViewDist;
836 int loc_FogRangeRecip;
839 int loc_LightPosition;
840 int loc_OffsetMapping_ScaleSteps;
841 int loc_OffsetMapping_LodDistance;
842 int loc_OffsetMapping_Bias;
844 int loc_ReflectColor;
845 int loc_ReflectFactor;
846 int loc_ReflectOffset;
847 int loc_RefractColor;
849 int loc_ScreenCenterRefractReflect;
850 int loc_ScreenScaleRefractReflect;
851 int loc_ScreenToDepth;
852 int loc_ShadowMap_Parameters;
853 int loc_ShadowMap_TextureScale;
854 int loc_SpecularPower;
855 int loc_Skeletal_Transform12;
860 int loc_ViewTintColor;
862 int loc_ModelToLight;
864 int loc_BackgroundTexMatrix;
865 int loc_ModelViewProjectionMatrix;
866 int loc_ModelViewMatrix;
867 int loc_PixelToScreenTexCoord;
868 int loc_ModelToReflectCube;
869 int loc_ShadowMapMatrix;
870 int loc_BloomColorSubtract;
871 int loc_NormalmapScrollBlend;
872 int loc_BounceGridMatrix;
873 int loc_BounceGridIntensity;
874 /// uniform block bindings
875 int ubibind_Skeletal_Transform12_UniformBlock;
876 /// uniform block indices
877 int ubiloc_Skeletal_Transform12_UniformBlock;
879 r_glsl_permutation_t;
881 #define SHADERPERMUTATION_HASHSIZE 256
884 // non-degradable "lightweight" shader parameters to keep the permutations simpler
885 // these can NOT degrade! only use for simple stuff
888 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
889 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
890 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
891 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
892 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
893 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
894 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
895 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
896 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
897 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
898 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
899 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
900 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
901 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
903 #define SHADERSTATICPARMS_COUNT 14
905 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
906 static int shaderstaticparms_count = 0;
908 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
909 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
911 extern qboolean r_shadow_shadowmapsampler;
912 extern int r_shadow_shadowmappcf;
913 qboolean R_CompileShader_CheckStaticParms(void)
915 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
916 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
917 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
920 if (r_glsl_saturation_redcompensate.integer)
921 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
922 if (r_glsl_vertextextureblend_usebothalphas.integer)
923 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
924 if (r_shadow_glossexact.integer)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
926 if (r_glsl_postprocess.integer)
928 if (r_glsl_postprocess_uservec1_enable.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
930 if (r_glsl_postprocess_uservec2_enable.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
932 if (r_glsl_postprocess_uservec3_enable.integer)
933 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
934 if (r_glsl_postprocess_uservec4_enable.integer)
935 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
938 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
939 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
940 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
942 if (r_shadow_shadowmapsampler)
943 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
944 if (r_shadow_shadowmappcf > 1)
945 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
946 else if (r_shadow_shadowmappcf)
947 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
948 if (r_celshading.integer)
949 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
950 if (r_celoutlines.integer)
951 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
953 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
956 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
957 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
958 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
960 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
961 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
963 shaderstaticparms_count = 0;
966 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
967 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
968 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
969 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
970 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
971 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
972 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
973 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
974 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
975 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
976 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
977 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
978 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
979 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
982 /// information about each possible shader permutation
983 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
984 /// currently selected permutation
985 r_glsl_permutation_t *r_glsl_permutation;
986 /// storage for permutations linked in the hash table
987 memexpandablearray_t r_glsl_permutationarray;
989 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
991 //unsigned int hashdepth = 0;
992 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
993 r_glsl_permutation_t *p;
994 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
996 if (p->mode == mode && p->permutation == permutation)
998 //if (hashdepth > 10)
999 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1004 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1006 p->permutation = permutation;
1007 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1008 r_glsl_permutationhash[mode][hashindex] = p;
1009 //if (hashdepth > 10)
1010 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1014 static char *R_ShaderStrCat(const char **strings)
1017 const char **p = strings;
1020 for (p = strings;(t = *p);p++)
1023 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1025 for (p = strings;(t = *p);p++)
1035 static char *R_ShaderStrCat(const char **strings);
1036 static void R_InitShaderModeInfo(void)
1039 shadermodeinfo_t *modeinfo;
1040 // we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine)
1041 for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1043 for (i = 0; i < SHADERMODE_COUNT; i++)
1045 char filename[MAX_QPATH];
1046 modeinfo = &shadermodeinfo[language][i];
1047 modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1048 modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1049 dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1050 modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1055 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1058 // if the mode has no filename we have to return the builtin string
1059 if (builtinonly || !modeinfo->filename)
1060 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1061 // note that FS_LoadFile appends a 0 byte to make it a valid string
1062 shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1065 if (printfromdisknotice)
1066 Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1067 return shaderstring;
1069 // fall back to builtinstring
1070 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1073 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1078 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1080 char permutationname[256];
1081 int vertstrings_count = 0;
1082 int geomstrings_count = 0;
1083 int fragstrings_count = 0;
1084 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1085 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1086 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1093 permutationname[0] = 0;
1094 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1096 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1098 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1099 if(vid.support.glshaderversion >= 140)
1101 vertstrings_list[vertstrings_count++] = "#version 140\n";
1102 geomstrings_list[geomstrings_count++] = "#version 140\n";
1103 fragstrings_list[fragstrings_count++] = "#version 140\n";
1104 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1105 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1106 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1108 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1109 else if(vid.support.glshaderversion >= 130)
1111 vertstrings_list[vertstrings_count++] = "#version 130\n";
1112 geomstrings_list[geomstrings_count++] = "#version 130\n";
1113 fragstrings_list[fragstrings_count++] = "#version 130\n";
1114 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1115 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1116 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1118 // if we can do #version 120, we should (this adds the invariant keyword)
1119 else if(vid.support.glshaderversion >= 120)
1121 vertstrings_list[vertstrings_count++] = "#version 120\n";
1122 geomstrings_list[geomstrings_count++] = "#version 120\n";
1123 fragstrings_list[fragstrings_count++] = "#version 120\n";
1124 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1125 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1126 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1128 // GLES also adds several things from GLSL120
1129 switch(vid.renderpath)
1131 case RENDERPATH_GLES2:
1132 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1133 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1134 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1140 // the first pretext is which type of shader to compile as
1141 // (later these will all be bound together as a program object)
1142 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1143 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1144 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1146 // the second pretext is the mode (for example a light source)
1147 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1148 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1149 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1150 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1152 // now add all the permutation pretexts
1153 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1155 if (permutation & (1ll<<i))
1157 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1158 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1159 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1160 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1164 // keep line numbers correct
1165 vertstrings_list[vertstrings_count++] = "\n";
1166 geomstrings_list[geomstrings_count++] = "\n";
1167 fragstrings_list[fragstrings_count++] = "\n";
1172 R_CompileShader_AddStaticParms(mode, permutation);
1173 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1174 vertstrings_count += shaderstaticparms_count;
1175 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1176 geomstrings_count += shaderstaticparms_count;
1177 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178 fragstrings_count += shaderstaticparms_count;
1180 // now append the shader text itself
1181 vertstrings_list[vertstrings_count++] = sourcestring;
1182 geomstrings_list[geomstrings_count++] = sourcestring;
1183 fragstrings_list[fragstrings_count++] = sourcestring;
1185 // compile the shader program
1186 if (vertstrings_count + geomstrings_count + fragstrings_count)
1187 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1191 qglUseProgram(p->program);CHECKGLERROR
1192 // look up all the uniform variable names we care about, so we don't
1193 // have to look them up every time we set them
1198 GLint activeuniformindex = 0;
1199 GLint numactiveuniforms = 0;
1200 char uniformname[128];
1201 GLsizei uniformnamelength = 0;
1202 GLint uniformsize = 0;
1203 GLenum uniformtype = 0;
1204 memset(uniformname, 0, sizeof(uniformname));
1205 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1206 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1207 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1209 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1210 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1215 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1216 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1217 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1218 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1219 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1220 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1221 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1222 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1223 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1224 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1225 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1226 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1227 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1228 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1229 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1230 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1231 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1232 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1233 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1234 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1235 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1236 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1237 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1238 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1239 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1240 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1241 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1242 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1243 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1244 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1245 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1246 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1247 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1248 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1249 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1250 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1251 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1252 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1253 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1254 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1255 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1256 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1257 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1258 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1259 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1260 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1261 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1262 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1263 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1264 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1265 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1266 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1267 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1268 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1269 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1270 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1271 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1272 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1273 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1274 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1275 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1276 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1277 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1278 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1279 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1280 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1281 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1282 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1283 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1284 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1285 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1286 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1287 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1288 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1289 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1290 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1291 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1292 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1293 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1294 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1295 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1296 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1297 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1298 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1299 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1300 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1301 // initialize the samplers to refer to the texture units we use
1302 p->tex_Texture_First = -1;
1303 p->tex_Texture_Second = -1;
1304 p->tex_Texture_GammaRamps = -1;
1305 p->tex_Texture_Normal = -1;
1306 p->tex_Texture_Color = -1;
1307 p->tex_Texture_Gloss = -1;
1308 p->tex_Texture_Glow = -1;
1309 p->tex_Texture_SecondaryNormal = -1;
1310 p->tex_Texture_SecondaryColor = -1;
1311 p->tex_Texture_SecondaryGloss = -1;
1312 p->tex_Texture_SecondaryGlow = -1;
1313 p->tex_Texture_Pants = -1;
1314 p->tex_Texture_Shirt = -1;
1315 p->tex_Texture_FogHeightTexture = -1;
1316 p->tex_Texture_FogMask = -1;
1317 p->tex_Texture_Lightmap = -1;
1318 p->tex_Texture_Deluxemap = -1;
1319 p->tex_Texture_Attenuation = -1;
1320 p->tex_Texture_Cube = -1;
1321 p->tex_Texture_Refraction = -1;
1322 p->tex_Texture_Reflection = -1;
1323 p->tex_Texture_ShadowMap2D = -1;
1324 p->tex_Texture_CubeProjection = -1;
1325 p->tex_Texture_ScreenNormalMap = -1;
1326 p->tex_Texture_ScreenDiffuse = -1;
1327 p->tex_Texture_ScreenSpecular = -1;
1328 p->tex_Texture_ReflectMask = -1;
1329 p->tex_Texture_ReflectCube = -1;
1330 p->tex_Texture_BounceGrid = -1;
1331 // bind the texture samplers in use
1333 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1334 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1335 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1336 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1337 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1338 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1339 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1340 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1341 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1342 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1343 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1344 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1345 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1346 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1347 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1348 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1349 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1350 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1351 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1352 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1353 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1354 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1355 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1356 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1357 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1358 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1359 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1360 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1361 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1362 // get the uniform block indices so we can bind them
1363 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1364 if (vid.support.arb_uniform_buffer_object)
1365 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1368 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1369 // clear the uniform block bindings
1370 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1371 // bind the uniform blocks in use
1373 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1374 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1376 // we're done compiling and setting up the shader, at least until it is used
1378 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1381 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1385 Mem_Free(sourcestring);
1388 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1390 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1391 if (r_glsl_permutation != perm)
1393 r_glsl_permutation = perm;
1394 if (!r_glsl_permutation->program)
1396 if (!r_glsl_permutation->compiled)
1398 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1399 R_GLSL_CompilePermutation(perm, mode, permutation);
1401 if (!r_glsl_permutation->program)
1403 // remove features until we find a valid permutation
1405 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1407 // reduce i more quickly whenever it would not remove any bits
1408 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1409 if (!(permutation & j))
1412 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1413 if (!r_glsl_permutation->compiled)
1414 R_GLSL_CompilePermutation(perm, mode, permutation);
1415 if (r_glsl_permutation->program)
1418 if (i >= SHADERPERMUTATION_COUNT)
1420 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1421 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1422 qglUseProgram(0);CHECKGLERROR
1423 return; // no bit left to clear, entire mode is broken
1428 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1430 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1431 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1432 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1440 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1441 extern D3DCAPS9 vid_d3d9caps;
1444 struct r_hlsl_permutation_s;
1445 typedef struct r_hlsl_permutation_s
1447 /// hash lookup data
1448 struct r_hlsl_permutation_s *hashnext;
1450 dpuint64 permutation;
1452 /// indicates if we have tried compiling this permutation already
1454 /// NULL if compilation failed
1455 IDirect3DVertexShader9 *vertexshader;
1456 IDirect3DPixelShader9 *pixelshader;
1458 r_hlsl_permutation_t;
1460 typedef enum D3DVSREGISTER_e
1462 D3DVSREGISTER_TexMatrix = 0, // float4x4
1463 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1464 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1465 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1466 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1467 D3DVSREGISTER_ModelToLight = 20, // float4x4
1468 D3DVSREGISTER_EyePosition = 24,
1469 D3DVSREGISTER_FogPlane = 25,
1470 D3DVSREGISTER_LightDir = 26,
1471 D3DVSREGISTER_LightPosition = 27,
1475 typedef enum D3DPSREGISTER_e
1477 D3DPSREGISTER_Alpha = 0,
1478 D3DPSREGISTER_BloomBlur_Parameters = 1,
1479 D3DPSREGISTER_ClientTime = 2,
1480 D3DPSREGISTER_Color_Ambient = 3,
1481 D3DPSREGISTER_Color_Diffuse = 4,
1482 D3DPSREGISTER_Color_Specular = 5,
1483 D3DPSREGISTER_Color_Glow = 6,
1484 D3DPSREGISTER_Color_Pants = 7,
1485 D3DPSREGISTER_Color_Shirt = 8,
1486 D3DPSREGISTER_DeferredColor_Ambient = 9,
1487 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1488 D3DPSREGISTER_DeferredColor_Specular = 11,
1489 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1490 D3DPSREGISTER_DeferredMod_Specular = 13,
1491 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1492 D3DPSREGISTER_EyePosition = 15, // unused
1493 D3DPSREGISTER_FogColor = 16,
1494 D3DPSREGISTER_FogHeightFade = 17,
1495 D3DPSREGISTER_FogPlane = 18,
1496 D3DPSREGISTER_FogPlaneViewDist = 19,
1497 D3DPSREGISTER_FogRangeRecip = 20,
1498 D3DPSREGISTER_LightColor = 21,
1499 D3DPSREGISTER_LightDir = 22, // unused
1500 D3DPSREGISTER_LightPosition = 23,
1501 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1502 D3DPSREGISTER_PixelSize = 25,
1503 D3DPSREGISTER_ReflectColor = 26,
1504 D3DPSREGISTER_ReflectFactor = 27,
1505 D3DPSREGISTER_ReflectOffset = 28,
1506 D3DPSREGISTER_RefractColor = 29,
1507 D3DPSREGISTER_Saturation = 30,
1508 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1509 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1510 D3DPSREGISTER_ScreenToDepth = 33,
1511 D3DPSREGISTER_ShadowMap_Parameters = 34,
1512 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1513 D3DPSREGISTER_SpecularPower = 36,
1514 D3DPSREGISTER_UserVec1 = 37,
1515 D3DPSREGISTER_UserVec2 = 38,
1516 D3DPSREGISTER_UserVec3 = 39,
1517 D3DPSREGISTER_UserVec4 = 40,
1518 D3DPSREGISTER_ViewTintColor = 41,
1519 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1520 D3DPSREGISTER_BloomColorSubtract = 43,
1521 D3DPSREGISTER_ViewToLight = 44, // float4x4
1522 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1523 D3DPSREGISTER_NormalmapScrollBlend = 52,
1524 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1525 D3DPSREGISTER_OffsetMapping_Bias = 54,
1530 /// information about each possible shader permutation
1531 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1532 /// currently selected permutation
1533 r_hlsl_permutation_t *r_hlsl_permutation;
1534 /// storage for permutations linked in the hash table
1535 memexpandablearray_t r_hlsl_permutationarray;
1537 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1539 //unsigned int hashdepth = 0;
1540 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1541 r_hlsl_permutation_t *p;
1542 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1544 if (p->mode == mode && p->permutation == permutation)
1546 //if (hashdepth > 10)
1547 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1552 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1554 p->permutation = permutation;
1555 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1556 r_hlsl_permutationhash[mode][hashindex] = p;
1557 //if (hashdepth > 10)
1558 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1563 //#include <d3dx9shader.h>
1564 //#include <d3dx9mesh.h>
1566 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1568 DWORD *vsbin = NULL;
1569 DWORD *psbin = NULL;
1570 fs_offset_t vsbinsize;
1571 fs_offset_t psbinsize;
1572 // IDirect3DVertexShader9 *vs = NULL;
1573 // IDirect3DPixelShader9 *ps = NULL;
1574 ID3DXBuffer *vslog = NULL;
1575 ID3DXBuffer *vsbuffer = NULL;
1576 ID3DXConstantTable *vsconstanttable = NULL;
1577 ID3DXBuffer *pslog = NULL;
1578 ID3DXBuffer *psbuffer = NULL;
1579 ID3DXConstantTable *psconstanttable = NULL;
1582 char temp[MAX_INPUTLINE];
1583 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1585 qboolean debugshader = gl_paranoid.integer != 0;
1586 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1587 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1590 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1591 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1593 if ((!vsbin && vertstring) || (!psbin && fragstring))
1595 const char* dllnames_d3dx9 [] =
1619 dllhandle_t d3dx9_dll = NULL;
1620 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1621 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1622 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1623 dllfunction_t d3dx9_dllfuncs[] =
1625 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1626 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1627 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1630 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1631 #ifndef ID3DXBuffer_GetBufferPointer
1632 #if !defined(__cplusplus) || defined(CINTERFACE)
1633 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1634 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1635 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1637 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1638 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1639 #define ID3DXBuffer_Release(p) (p)->Release()
1642 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1644 DWORD shaderflags = 0;
1646 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1647 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1648 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1649 if (vertstring && vertstring[0])
1653 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1654 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1657 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1660 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1661 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1662 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1663 ID3DXBuffer_Release(vsbuffer);
1667 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1668 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1669 ID3DXBuffer_Release(vslog);
1672 if (fragstring && fragstring[0])
1676 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1677 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1680 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1683 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1684 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1685 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1686 ID3DXBuffer_Release(psbuffer);
1690 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1691 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1692 ID3DXBuffer_Release(pslog);
1695 Sys_UnloadLibrary(&d3dx9_dll);
1698 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1702 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1703 if (FAILED(vsresult))
1704 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1705 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1706 if (FAILED(psresult))
1707 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1709 // free the shader data
1710 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1711 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1714 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1717 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1718 int vertstring_length = 0;
1719 int geomstring_length = 0;
1720 int fragstring_length = 0;
1723 char *vertstring, *geomstring, *fragstring;
1724 char permutationname[256];
1725 char cachename[256];
1726 int vertstrings_count = 0;
1727 int geomstrings_count = 0;
1728 int fragstrings_count = 0;
1729 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1730 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1731 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1736 p->vertexshader = NULL;
1737 p->pixelshader = NULL;
1739 permutationname[0] = 0;
1741 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1743 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1744 strlcat(cachename, "hlsl/", sizeof(cachename));
1746 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1747 vertstrings_count = 0;
1748 geomstrings_count = 0;
1749 fragstrings_count = 0;
1750 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1751 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1752 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1754 // the first pretext is which type of shader to compile as
1755 // (later these will all be bound together as a program object)
1756 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1757 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1758 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1760 // the second pretext is the mode (for example a light source)
1761 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1762 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1763 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1764 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1765 strlcat(cachename, modeinfo->name, sizeof(cachename));
1767 // now add all the permutation pretexts
1768 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1770 if (permutation & (1ll<<i))
1772 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1773 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1774 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1775 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1776 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1780 // keep line numbers correct
1781 vertstrings_list[vertstrings_count++] = "\n";
1782 geomstrings_list[geomstrings_count++] = "\n";
1783 fragstrings_list[fragstrings_count++] = "\n";
1788 R_CompileShader_AddStaticParms(mode, permutation);
1789 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1790 vertstrings_count += shaderstaticparms_count;
1791 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1792 geomstrings_count += shaderstaticparms_count;
1793 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794 fragstrings_count += shaderstaticparms_count;
1796 // replace spaces in the cachename with _ characters
1797 for (i = 0;cachename[i];i++)
1798 if (cachename[i] == ' ')
1801 // now append the shader text itself
1802 vertstrings_list[vertstrings_count++] = sourcestring;
1803 geomstrings_list[geomstrings_count++] = sourcestring;
1804 fragstrings_list[fragstrings_count++] = sourcestring;
1806 vertstring_length = 0;
1807 for (i = 0;i < vertstrings_count;i++)
1808 vertstring_length += (int)strlen(vertstrings_list[i]);
1809 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1810 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1811 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1813 geomstring_length = 0;
1814 for (i = 0;i < geomstrings_count;i++)
1815 geomstring_length += (int)strlen(geomstrings_list[i]);
1816 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1817 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1818 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1820 fragstring_length = 0;
1821 for (i = 0;i < fragstrings_count;i++)
1822 fragstring_length += (int)strlen(fragstrings_list[i]);
1823 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1824 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1825 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1827 // try to load the cached shader, or generate one
1828 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1830 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1831 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1833 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1837 Mem_Free(vertstring);
1839 Mem_Free(geomstring);
1841 Mem_Free(fragstring);
1843 Mem_Free(sourcestring);
1846 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1847 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1848 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1849 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1850 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1851 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1853 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1854 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1855 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1856 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1857 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1858 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1860 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1862 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1863 if (r_hlsl_permutation != perm)
1865 r_hlsl_permutation = perm;
1866 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1868 if (!r_hlsl_permutation->compiled)
1869 R_HLSL_CompilePermutation(perm, mode, permutation);
1870 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1872 // remove features until we find a valid permutation
1874 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1876 // reduce i more quickly whenever it would not remove any bits
1877 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1878 if (!(permutation & j))
1881 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1882 if (!r_hlsl_permutation->compiled)
1883 R_HLSL_CompilePermutation(perm, mode, permutation);
1884 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1887 if (i >= SHADERPERMUTATION_COUNT)
1889 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1890 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1891 return; // no bit left to clear, entire mode is broken
1895 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1896 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1898 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1899 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1900 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1904 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1906 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1907 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1908 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1909 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1912 void R_GLSL_Restart_f(void)
1914 unsigned int i, limit;
1915 switch(vid.renderpath)
1917 case RENDERPATH_D3D9:
1920 r_hlsl_permutation_t *p;
1921 r_hlsl_permutation = NULL;
1922 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1923 for (i = 0;i < limit;i++)
1925 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1927 if (p->vertexshader)
1928 IDirect3DVertexShader9_Release(p->vertexshader);
1930 IDirect3DPixelShader9_Release(p->pixelshader);
1931 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1934 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1938 case RENDERPATH_D3D10:
1939 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1941 case RENDERPATH_D3D11:
1942 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944 case RENDERPATH_GL20:
1945 case RENDERPATH_GLES2:
1947 r_glsl_permutation_t *p;
1948 r_glsl_permutation = NULL;
1949 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1950 for (i = 0;i < limit;i++)
1952 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1954 GL_Backend_FreeProgram(p->program);
1955 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1958 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1961 case RENDERPATH_GL11:
1962 case RENDERPATH_GL13:
1963 case RENDERPATH_GLES1:
1965 case RENDERPATH_SOFT:
1970 static void R_GLSL_DumpShader_f(void)
1972 int i, language, mode, dupe;
1974 shadermodeinfo_t *modeinfo;
1977 for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1979 modeinfo = shadermodeinfo[language];
1980 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1982 // don't dump the same file multiple times (most or all shaders come from the same file)
1983 for (dupe = mode - 1;dupe >= 0;dupe--)
1984 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1988 text = modeinfo[mode].builtinstring;
1991 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1994 FS_Print(file, "/* The engine may define the following macros:\n");
1995 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1996 for (i = 0;i < SHADERMODE_COUNT;i++)
1997 FS_Print(file, modeinfo[i].pretext);
1998 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1999 FS_Print(file, shaderpermutationinfo[i].pretext);
2000 FS_Print(file, "*/\n");
2001 FS_Print(file, text);
2003 Con_Printf("%s written\n", modeinfo[mode].filename);
2006 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2011 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2013 dpuint64 permutation = 0;
2014 if (r_trippy.integer && !notrippy)
2015 permutation |= SHADERPERMUTATION_TRIPPY;
2016 permutation |= SHADERPERMUTATION_VIEWTINT;
2018 permutation |= SHADERPERMUTATION_DIFFUSE;
2020 permutation |= SHADERPERMUTATION_SPECULAR;
2021 if (texturemode == GL_MODULATE)
2022 permutation |= SHADERPERMUTATION_COLORMAPPING;
2023 else if (texturemode == GL_ADD)
2024 permutation |= SHADERPERMUTATION_GLOW;
2025 else if (texturemode == GL_DECAL)
2026 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2027 if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2028 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2029 if (suppresstexalpha)
2030 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2032 texturemode = GL_MODULATE;
2033 if (vid.allowalphatocoverage)
2034 GL_AlphaToCoverage(false);
2035 switch (vid.renderpath)
2037 case RENDERPATH_D3D9:
2039 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2040 R_Mesh_TexBind(GL20TU_FIRST , first );
2041 R_Mesh_TexBind(GL20TU_SECOND, second);
2042 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2043 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2046 case RENDERPATH_D3D10:
2047 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2049 case RENDERPATH_D3D11:
2050 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2052 case RENDERPATH_GL20:
2053 case RENDERPATH_GLES2:
2054 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2055 if (r_glsl_permutation->tex_Texture_First >= 0)
2056 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2057 if (r_glsl_permutation->tex_Texture_Second >= 0)
2058 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2059 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2060 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2062 case RENDERPATH_GL13:
2063 case RENDERPATH_GLES1:
2064 R_Mesh_TexBind(0, first );
2065 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2066 R_Mesh_TexMatrix(0, NULL);
2067 R_Mesh_TexBind(1, second);
2070 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2071 R_Mesh_TexMatrix(1, NULL);
2074 case RENDERPATH_GL11:
2075 R_Mesh_TexBind(0, first );
2076 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2077 R_Mesh_TexMatrix(0, NULL);
2079 case RENDERPATH_SOFT:
2080 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2081 R_Mesh_TexBind(GL20TU_FIRST , first );
2082 R_Mesh_TexBind(GL20TU_SECOND, second);
2087 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2089 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2092 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2094 dpuint64 permutation = 0;
2095 if (r_trippy.integer && !notrippy)
2096 permutation |= SHADERPERMUTATION_TRIPPY;
2098 permutation |= SHADERPERMUTATION_DEPTHRGB;
2100 permutation |= SHADERPERMUTATION_SKELETAL;
2102 if (vid.allowalphatocoverage)
2103 GL_AlphaToCoverage(false);
2104 switch (vid.renderpath)
2106 case RENDERPATH_D3D9:
2108 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2111 case RENDERPATH_D3D10:
2112 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2114 case RENDERPATH_D3D11:
2115 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2117 case RENDERPATH_GL20:
2118 case RENDERPATH_GLES2:
2119 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2120 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2121 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2124 case RENDERPATH_GL13:
2125 case RENDERPATH_GLES1:
2126 R_Mesh_TexBind(0, 0);
2127 R_Mesh_TexBind(1, 0);
2129 case RENDERPATH_GL11:
2130 R_Mesh_TexBind(0, 0);
2132 case RENDERPATH_SOFT:
2133 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2138 #define BLENDFUNC_ALLOWS_COLORMOD 1
2139 #define BLENDFUNC_ALLOWS_FOG 2
2140 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2141 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2142 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2143 static int R_BlendFuncFlags(int src, int dst)
2147 // a blendfunc allows colormod if:
2148 // a) it can never keep the destination pixel invariant, or
2149 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2150 // this is to prevent unintended side effects from colormod
2152 // a blendfunc allows fog if:
2153 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2154 // this is to prevent unintended side effects from fog
2156 // these checks are the output of fogeval.pl
2158 r |= BLENDFUNC_ALLOWS_COLORMOD;
2159 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2160 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2161 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2162 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2163 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2164 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2166 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2167 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2168 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2169 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2170 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2171 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2172 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2173 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2174 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2175 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2176 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2177 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2178 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2179 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2184 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2186 // select a permutation of the lighting shader appropriate to this
2187 // combination of texture, entity, light source, and fogging, only use the
2188 // minimum features necessary to avoid wasting rendering time in the
2189 // fragment shader on features that are not being used
2190 dpuint64 permutation = 0;
2191 unsigned int mode = 0;
2193 texture_t *t = rsurface.texture;
2195 matrix4x4_t tempmatrix;
2196 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2197 if (r_trippy.integer && !notrippy)
2198 permutation |= SHADERPERMUTATION_TRIPPY;
2199 if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2200 permutation |= SHADERPERMUTATION_ALPHAKILL;
2201 if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2202 permutation |= SHADERPERMUTATION_OCCLUDE;
2203 if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2204 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2205 if (rsurfacepass == RSURFPASS_BACKGROUND)
2207 // distorted background
2208 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2210 mode = SHADERMODE_WATER;
2211 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2212 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2213 if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2215 // this is the right thing to do for wateralpha
2216 GL_BlendFunc(GL_ONE, GL_ZERO);
2217 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2221 // this is the right thing to do for entity alpha
2222 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2223 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2226 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2228 mode = SHADERMODE_REFRACTION;
2229 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2230 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2231 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2232 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2236 mode = SHADERMODE_GENERIC;
2237 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2238 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2239 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241 if (vid.allowalphatocoverage)
2242 GL_AlphaToCoverage(false);
2244 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2246 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2248 switch(t->offsetmapping)
2250 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2251 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2252 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2253 case OFFSETMAPPING_OFF: break;
2256 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2257 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2258 // normalmap (deferred prepass), may use alpha test on diffuse
2259 mode = SHADERMODE_DEFERREDGEOMETRY;
2260 GL_BlendFunc(GL_ONE, GL_ZERO);
2261 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2262 if (vid.allowalphatocoverage)
2263 GL_AlphaToCoverage(false);
2265 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2267 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2269 switch(t->offsetmapping)
2271 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2272 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2273 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2274 case OFFSETMAPPING_OFF: break;
2277 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2278 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2279 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2280 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2282 mode = SHADERMODE_LIGHTSOURCE;
2283 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2284 permutation |= SHADERPERMUTATION_CUBEFILTER;
2285 if (VectorLength2(rtlightdiffuse) > 0)
2286 permutation |= SHADERPERMUTATION_DIFFUSE;
2287 if (VectorLength2(rtlightspecular) > 0)
2288 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2289 if (r_refdef.fogenabled)
2290 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2291 if (t->colormapping)
2292 permutation |= SHADERPERMUTATION_COLORMAPPING;
2293 if (r_shadow_usingshadowmap2d)
2295 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2296 if(r_shadow_shadowmapvsdct)
2297 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2299 if (r_shadow_shadowmap2ddepthbuffer)
2300 permutation |= SHADERPERMUTATION_DEPTHRGB;
2302 if (t->reflectmasktexture)
2303 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2304 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2305 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2306 if (vid.allowalphatocoverage)
2307 GL_AlphaToCoverage(false);
2309 else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2311 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2313 switch(t->offsetmapping)
2315 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2316 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2317 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2318 case OFFSETMAPPING_OFF: break;
2321 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2322 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2323 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2324 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2325 // directional model lighting
2326 mode = SHADERMODE_LIGHTDIRECTION;
2327 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2328 permutation |= SHADERPERMUTATION_GLOW;
2329 if (VectorLength2(t->render_modellight_diffuse))
2330 permutation |= SHADERPERMUTATION_DIFFUSE;
2331 if (VectorLength2(t->render_modellight_specular) > 0)
2332 permutation |= SHADERPERMUTATION_SPECULAR;
2333 if (r_refdef.fogenabled)
2334 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2335 if (t->colormapping)
2336 permutation |= SHADERPERMUTATION_COLORMAPPING;
2337 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2339 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2340 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2342 if (r_shadow_shadowmap2ddepthbuffer)
2343 permutation |= SHADERPERMUTATION_DEPTHRGB;
2345 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2346 permutation |= SHADERPERMUTATION_REFLECTION;
2347 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2348 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2349 if (t->reflectmasktexture)
2350 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2351 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2353 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2354 if (r_shadow_bouncegrid_state.directional)
2355 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2357 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2358 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2359 // when using alphatocoverage, we don't need alphakill
2360 if (vid.allowalphatocoverage)
2362 if (r_transparent_alphatocoverage.integer)
2364 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2365 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2368 GL_AlphaToCoverage(false);
2373 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2375 switch(t->offsetmapping)
2377 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2378 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2379 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2380 case OFFSETMAPPING_OFF: break;
2383 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2384 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2385 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2386 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2388 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2389 permutation |= SHADERPERMUTATION_GLOW;
2390 if (r_refdef.fogenabled)
2391 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2392 if (t->colormapping)
2393 permutation |= SHADERPERMUTATION_COLORMAPPING;
2394 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2396 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2397 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2399 if (r_shadow_shadowmap2ddepthbuffer)
2400 permutation |= SHADERPERMUTATION_DEPTHRGB;
2402 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2403 permutation |= SHADERPERMUTATION_REFLECTION;
2404 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2405 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2406 if (t->reflectmasktexture)
2407 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2408 if (FAKELIGHT_ENABLED)
2410 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2411 mode = SHADERMODE_FAKELIGHT;
2412 permutation |= SHADERPERMUTATION_DIFFUSE;
2413 if (VectorLength2(t->render_lightmap_specular) > 0)
2414 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2416 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2418 // deluxemapping (light direction texture)
2419 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2420 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2422 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2423 permutation |= SHADERPERMUTATION_DIFFUSE;
2424 if (VectorLength2(t->render_lightmap_specular) > 0)
2425 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2427 else if (r_glsl_deluxemapping.integer >= 2)
2429 // fake deluxemapping (uniform light direction in tangentspace)
2430 if (rsurface.uselightmaptexture)
2431 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2433 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2434 permutation |= SHADERPERMUTATION_DIFFUSE;
2435 if (VectorLength2(t->render_lightmap_specular) > 0)
2436 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2438 else if (rsurface.uselightmaptexture)
2440 // ordinary lightmapping (q1bsp, q3bsp)
2441 mode = SHADERMODE_LIGHTMAP;
2445 // ordinary vertex coloring (q3bsp)
2446 mode = SHADERMODE_VERTEXCOLOR;
2448 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2450 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2451 if (r_shadow_bouncegrid_state.directional)
2452 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2454 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2455 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2456 // when using alphatocoverage, we don't need alphakill
2457 if (vid.allowalphatocoverage)
2459 if (r_transparent_alphatocoverage.integer)
2461 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2462 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2465 GL_AlphaToCoverage(false);
2468 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2469 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2470 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2471 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2472 switch(vid.renderpath)
2474 case RENDERPATH_D3D9:
2476 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2477 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2478 R_SetupShader_SetPermutationHLSL(mode, permutation);
2479 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2480 if (mode == SHADERMODE_LIGHTSOURCE)
2482 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2483 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2487 if (mode == SHADERMODE_LIGHTDIRECTION)
2489 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2492 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2493 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2494 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2495 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2496 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2498 if (mode == SHADERMODE_LIGHTSOURCE)
2500 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2501 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2502 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2503 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2504 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2506 // additive passes are only darkened by fog, not tinted
2507 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2508 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2512 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2513 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2514 if (mode == SHADERMODE_FLATCOLOR)
2516 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2518 else if (mode == SHADERMODE_LIGHTDIRECTION)
2520 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2521 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2522 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2523 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2524 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2528 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2529 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2530 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2532 // additive passes are only darkened by fog, not tinted
2533 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2534 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2536 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2537 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2538 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2539 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2540 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2541 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2542 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2543 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2544 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2545 if (mode == SHADERMODE_WATER)
2546 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2548 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2550 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2551 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2555 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2556 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2558 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2559 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2560 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2561 if (t->pantstexture)
2562 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2564 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2565 if (t->shirttexture)
2566 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2568 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2569 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2570 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2571 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2572 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2573 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2574 r_glsl_offsetmapping_scale.value*t->offsetscale,
2575 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2576 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2577 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2579 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2580 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2581 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2582 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2584 R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture );
2585 R_Mesh_TexBind(GL20TU_COLOR , t->basetexture );
2586 R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture );
2587 R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture );
2588 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture );
2589 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture );
2590 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture );
2591 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture );
2592 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture );
2593 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture );
2594 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture );
2595 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2596 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2597 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2598 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2599 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2600 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2601 if (rsurfacepass == RSURFPASS_BACKGROUND)
2603 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2604 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2605 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2609 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2611 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2612 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2613 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2614 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2616 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2617 if (rsurface.rtlight)
2619 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2620 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2625 case RENDERPATH_D3D10:
2626 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2628 case RENDERPATH_D3D11:
2629 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2631 case RENDERPATH_GL20:
2632 case RENDERPATH_GLES2:
2633 if (!vid.useinterleavedarrays)
2635 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2636 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2637 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2638 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2639 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2640 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2641 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2642 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2643 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2644 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2645 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2649 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2650 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2652 // this has to be after RSurf_PrepareVerticesForBatch
2653 if (rsurface.batchskeletaltransform3x4buffer)
2654 permutation |= SHADERPERMUTATION_SKELETAL;
2655 R_SetupShader_SetPermutationGLSL(mode, permutation);
2656 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2657 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2659 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2660 if (mode == SHADERMODE_LIGHTSOURCE)
2662 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2663 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2664 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2665 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2666 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2667 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2669 // additive passes are only darkened by fog, not tinted
2670 if (r_glsl_permutation->loc_FogColor >= 0)
2671 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2672 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2676 if (mode == SHADERMODE_FLATCOLOR)
2678 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2680 else if (mode == SHADERMODE_LIGHTDIRECTION)
2682 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2683 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2684 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2685 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2686 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2687 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2688 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2692 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2693 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2694 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2695 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2696 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2698 // additive passes are only darkened by fog, not tinted
2699 if (r_glsl_permutation->loc_FogColor >= 0)
2701 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2702 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2704 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2706 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2707 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2708 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2709 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2710 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2711 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2712 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2713 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2714 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2716 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2717 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2718 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2719 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2721 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2722 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2726 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2727 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2730 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2731 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2732 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2733 if (r_glsl_permutation->loc_Color_Pants >= 0)
2735 if (t->pantstexture)
2736 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2738 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2740 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2742 if (t->shirttexture)
2743 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2745 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2747 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2748 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2749 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2750 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2751 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2752 r_glsl_offsetmapping_scale.value*t->offsetscale,
2753 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2754 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2755 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2757 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2758 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2759 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2760 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2761 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2762 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2764 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2765 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2766 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2767 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , t->nmaptexture );
2768 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , t->basetexture );
2769 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , t->glosstexture );
2770 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , t->glowtexture );
2771 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , t->backgroundnmaptexture );
2772 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , t->backgroundbasetexture );
2773 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , t->backgroundglosstexture );
2774 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , t->backgroundglowtexture );
2775 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , t->pantstexture );
2776 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , t->shirttexture );
2777 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , t->reflectmasktexture );
2778 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2779 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2780 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2781 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2782 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2783 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2784 if (rsurfacepass == RSURFPASS_BACKGROUND)
2786 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2787 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2788 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2792 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2794 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2795 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2796 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2797 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2799 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2800 if (rsurface.rtlight)
2802 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2803 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2806 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2809 case RENDERPATH_GL11:
2810 case RENDERPATH_GL13:
2811 case RENDERPATH_GLES1:
2813 case RENDERPATH_SOFT:
2814 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2815 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2816 R_SetupShader_SetPermutationSoft(mode, permutation);
2817 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2818 if (mode == SHADERMODE_LIGHTSOURCE)
2820 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2821 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2822 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2823 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2824 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2825 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2827 // additive passes are only darkened by fog, not tinted
2828 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2829 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2833 if (mode == SHADERMODE_FLATCOLOR)
2835 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2837 else if (mode == SHADERMODE_LIGHTDIRECTION)
2839 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2840 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2841 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2842 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2843 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2847 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2848 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2849 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2851 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2852 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2853 // additive passes are only darkened by fog, not tinted
2854 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2855 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2857 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2858 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2859 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2860 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2861 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2862 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2863 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2864 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2865 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2866 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2868 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2869 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2870 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2871 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2873 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2874 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2878 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2879 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2882 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2883 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2885 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2887 if (t->pantstexture)
2888 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2890 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2892 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2894 if (t->shirttexture)
2895 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2897 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2899 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2900 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2901 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2902 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2903 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2904 r_glsl_offsetmapping_scale.value*t->offsetscale,
2905 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2906 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2907 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2909 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2910 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2911 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2912 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2914 R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture );
2915 R_Mesh_TexBind(GL20TU_COLOR , t->basetexture );
2916 R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture );
2917 R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture );
2918 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture );
2919 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture );
2920 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture );
2921 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture );
2922 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture );
2923 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture );
2924 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture );
2925 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2926 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2927 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2928 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2929 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2930 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2931 if (rsurfacepass == RSURFPASS_BACKGROUND)
2933 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2934 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2935 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2939 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2941 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2942 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2943 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2944 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2946 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2947 if (rsurface.rtlight)
2949 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2950 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2957 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2959 // select a permutation of the lighting shader appropriate to this
2960 // combination of texture, entity, light source, and fogging, only use the
2961 // minimum features necessary to avoid wasting rendering time in the
2962 // fragment shader on features that are not being used
2963 dpuint64 permutation = 0;
2964 unsigned int mode = 0;
2965 const float *lightcolorbase = rtlight->currentcolor;
2966 float ambientscale = rtlight->ambientscale;
2967 float diffusescale = rtlight->diffusescale;
2968 float specularscale = rtlight->specularscale;
2969 // this is the location of the light in view space
2970 vec3_t viewlightorigin;
2971 // this transforms from view space (camera) to light space (cubemap)
2972 matrix4x4_t viewtolight;
2973 matrix4x4_t lighttoview;
2974 float viewtolight16f[16];
2976 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2977 if (rtlight->currentcubemap != r_texture_whitecube)
2978 permutation |= SHADERPERMUTATION_CUBEFILTER;
2979 if (diffusescale > 0)
2980 permutation |= SHADERPERMUTATION_DIFFUSE;
2981 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2982 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2983 if (r_shadow_usingshadowmap2d)
2985 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2986 if (r_shadow_shadowmapvsdct)
2987 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2989 if (r_shadow_shadowmap2ddepthbuffer)
2990 permutation |= SHADERPERMUTATION_DEPTHRGB;
2992 if (vid.allowalphatocoverage)
2993 GL_AlphaToCoverage(false);
2994 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2995 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2996 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
2997 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2998 switch(vid.renderpath)
3000 case RENDERPATH_D3D9:
3002 R_SetupShader_SetPermutationHLSL(mode, permutation);
3003 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3004 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3005 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3006 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3007 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3008 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3009 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3010 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3011 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3012 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3014 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3015 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3016 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3017 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3018 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3021 case RENDERPATH_D3D10:
3022 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3024 case RENDERPATH_D3D11:
3025 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3027 case RENDERPATH_GL20:
3028 case RENDERPATH_GLES2:
3029 R_SetupShader_SetPermutationGLSL(mode, permutation);
3030 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3031 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3032 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3033 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3034 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3035 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3036 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3037 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3038 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3039 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3041 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3042 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3043 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3044 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3045 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3047 case RENDERPATH_GL11:
3048 case RENDERPATH_GL13:
3049 case RENDERPATH_GLES1:
3051 case RENDERPATH_SOFT:
3052 R_SetupShader_SetPermutationGLSL(mode, permutation);
3053 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3054 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3055 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3056 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3057 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3058 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3059 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3060 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3061 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3062 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3064 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3065 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3066 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3067 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3068 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3073 #define SKINFRAME_HASH 1024
3077 unsigned int loadsequence; // incremented each level change
3078 memexpandablearray_t array;
3079 skinframe_t *hash[SKINFRAME_HASH];
3082 r_skinframe_t r_skinframe;
3084 void R_SkinFrame_PrepareForPurge(void)
3086 r_skinframe.loadsequence++;
3087 // wrap it without hitting zero
3088 if (r_skinframe.loadsequence >= 200)
3089 r_skinframe.loadsequence = 1;
3092 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3096 // mark the skinframe as used for the purging code
3097 skinframe->loadsequence = r_skinframe.loadsequence;
3100 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3102 if (s->merged == s->base)
3104 R_PurgeTexture(s->stain); s->stain = NULL;
3105 R_PurgeTexture(s->merged); s->merged = NULL;
3106 R_PurgeTexture(s->base); s->base = NULL;
3107 R_PurgeTexture(s->pants); s->pants = NULL;
3108 R_PurgeTexture(s->shirt); s->shirt = NULL;
3109 R_PurgeTexture(s->nmap); s->nmap = NULL;
3110 R_PurgeTexture(s->gloss); s->gloss = NULL;
3111 R_PurgeTexture(s->glow); s->glow = NULL;
3112 R_PurgeTexture(s->fog); s->fog = NULL;
3113 R_PurgeTexture(s->reflect); s->reflect = NULL;
3114 s->loadsequence = 0;
3117 void R_SkinFrame_Purge(void)
3121 for (i = 0;i < SKINFRAME_HASH;i++)
3123 for (s = r_skinframe.hash[i];s;s = s->next)
3125 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3126 R_SkinFrame_PurgeSkinFrame(s);
3131 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3133 char basename[MAX_QPATH];
3135 Image_StripImageExtension(name, basename, sizeof(basename));
3137 if( last == NULL ) {
3139 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3140 item = r_skinframe.hash[hashindex];
3145 // linearly search through the hash bucket
3146 for( ; item ; item = item->next ) {
3147 if( !strcmp( item->basename, basename ) ) {
3154 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3158 char basename[MAX_QPATH];
3160 Image_StripImageExtension(name, basename, sizeof(basename));
3162 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3163 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3164 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3171 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3172 memset(item, 0, sizeof(*item));
3173 strlcpy(item->basename, basename, sizeof(item->basename));
3174 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3175 item->comparewidth = comparewidth;
3176 item->compareheight = compareheight;
3177 item->comparecrc = comparecrc;
3178 item->next = r_skinframe.hash[hashindex];
3179 r_skinframe.hash[hashindex] = item;
3181 else if (textureflags & TEXF_FORCE_RELOAD)
3185 R_SkinFrame_PurgeSkinFrame(item);
3188 R_SkinFrame_MarkUsed(item);
3192 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3194 unsigned long long avgcolor[5], wsum; \
3202 for(pix = 0; pix < cnt; ++pix) \
3205 for(comp = 0; comp < 3; ++comp) \
3207 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3210 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3212 for(comp = 0; comp < 3; ++comp) \
3213 avgcolor[comp] += getpixel * w; \
3216 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3217 avgcolor[4] += getpixel; \
3219 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3221 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3222 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3223 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3224 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3227 extern cvar_t gl_picmip;
3228 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3231 unsigned char *pixels;
3232 unsigned char *bumppixels;
3233 unsigned char *basepixels = NULL;
3234 int basepixels_width = 0;
3235 int basepixels_height = 0;
3236 skinframe_t *skinframe;
3237 rtexture_t *ddsbase = NULL;
3238 qboolean ddshasalpha = false;
3239 float ddsavgcolor[4];
3240 char basename[MAX_QPATH];
3241 int miplevel = R_PicmipForFlags(textureflags);
3242 int savemiplevel = miplevel;
3246 if (cls.state == ca_dedicated)
3249 // return an existing skinframe if already loaded
3250 // if loading of the first image fails, don't make a new skinframe as it
3251 // would cause all future lookups of this to be missing
3252 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3253 if (skinframe && skinframe->base)
3256 Image_StripImageExtension(name, basename, sizeof(basename));
3258 // check for DDS texture file first
3259 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3261 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3262 if (basepixels == NULL && fallbacknotexture)
3263 basepixels = Image_GenerateNoTexture();
3264 if (basepixels == NULL)
3268 // FIXME handle miplevel
3270 if (developer_loading.integer)
3271 Con_Printf("loading skin \"%s\"\n", name);
3273 // we've got some pixels to store, so really allocate this new texture now
3275 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3276 textureflags &= ~TEXF_FORCE_RELOAD;
3277 skinframe->stain = NULL;
3278 skinframe->merged = NULL;
3279 skinframe->base = NULL;
3280 skinframe->pants = NULL;
3281 skinframe->shirt = NULL;
3282 skinframe->nmap = NULL;
3283 skinframe->gloss = NULL;
3284 skinframe->glow = NULL;
3285 skinframe->fog = NULL;
3286 skinframe->reflect = NULL;
3287 skinframe->hasalpha = false;
3288 // we could store the q2animname here too
3292 skinframe->base = ddsbase;
3293 skinframe->hasalpha = ddshasalpha;
3294 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3295 if (r_loadfog && skinframe->hasalpha)
3296 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3297 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3301 basepixels_width = image_width;
3302 basepixels_height = image_height;
3303 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3304 if (textureflags & TEXF_ALPHA)
3306 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3308 if (basepixels[j] < 255)
3310 skinframe->hasalpha = true;
3314 if (r_loadfog && skinframe->hasalpha)
3316 // has transparent pixels
3317 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3318 for (j = 0;j < image_width * image_height * 4;j += 4)
3323 pixels[j+3] = basepixels[j+3];
3325 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3329 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3331 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3332 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3333 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3334 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3335 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3341 mymiplevel = savemiplevel;
3342 if (r_loadnormalmap)
3343 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3344 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3346 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3347 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3348 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3349 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3352 // _norm is the name used by tenebrae and has been adopted as standard
3353 if (r_loadnormalmap && skinframe->nmap == NULL)
3355 mymiplevel = savemiplevel;
3356 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3358 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3362 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3364 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3365 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3366 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3368 Mem_Free(bumppixels);
3370 else if (r_shadow_bumpscale_basetexture.value > 0)
3372 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3373 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3374 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3378 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3379 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3383 // _luma is supported only for tenebrae compatibility
3384 // _glow is the preferred name
3385 mymiplevel = savemiplevel;
3386 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3388 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3390 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3391 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3393 Mem_Free(pixels);pixels = NULL;
3396 mymiplevel = savemiplevel;
3397 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3399 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3401 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3402 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3408 mymiplevel = savemiplevel;
3409 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3411 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3413 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3414 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3420 mymiplevel = savemiplevel;
3421 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3423 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3425 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3426 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3432 mymiplevel = savemiplevel;
3433 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3435 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3437 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3438 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3445 Mem_Free(basepixels);
3450 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3451 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3454 skinframe_t *skinframe;
3457 if (cls.state == ca_dedicated)
3460 // if already loaded just return it, otherwise make a new skinframe
3461 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3462 if (skinframe->base)
3464 textureflags &= ~TEXF_FORCE_RELOAD;
3466 skinframe->stain = NULL;
3467 skinframe->merged = NULL;
3468 skinframe->base = NULL;
3469 skinframe->pants = NULL;
3470 skinframe->shirt = NULL;
3471 skinframe->nmap = NULL;
3472 skinframe->gloss = NULL;
3473 skinframe->glow = NULL;
3474 skinframe->fog = NULL;
3475 skinframe->reflect = NULL;
3476 skinframe->hasalpha = false;
3478 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3482 if (developer_loading.integer)
3483 Con_Printf("loading 32bit skin \"%s\"\n", name);
3485 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3487 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3488 unsigned char *b = a + width * height * 4;
3489 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3490 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3493 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3494 if (textureflags & TEXF_ALPHA)
3496 for (i = 3;i < width * height * 4;i += 4)
3498 if (skindata[i] < 255)
3500 skinframe->hasalpha = true;
3504 if (r_loadfog && skinframe->hasalpha)
3506 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3507 memcpy(fogpixels, skindata, width * height * 4);
3508 for (i = 0;i < width * height * 4;i += 4)
3509 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3510 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3511 Mem_Free(fogpixels);
3515 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3516 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3521 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3525 skinframe_t *skinframe;
3527 if (cls.state == ca_dedicated)
3530 // if already loaded just return it, otherwise make a new skinframe
3531 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3532 if (skinframe->base)
3534 //textureflags &= ~TEXF_FORCE_RELOAD;
3536 skinframe->stain = NULL;
3537 skinframe->merged = NULL;
3538 skinframe->base = NULL;
3539 skinframe->pants = NULL;
3540 skinframe->shirt = NULL;
3541 skinframe->nmap = NULL;
3542 skinframe->gloss = NULL;
3543 skinframe->glow = NULL;
3544 skinframe->fog = NULL;
3545 skinframe->reflect = NULL;
3546 skinframe->hasalpha = false;
3548 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3552 if (developer_loading.integer)
3553 Con_Printf("loading quake skin \"%s\"\n", name);
3555 // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3556 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3557 memcpy(skinframe->qpixels, skindata, width*height);
3558 skinframe->qwidth = width;
3559 skinframe->qheight = height;
3562 for (i = 0;i < width * height;i++)
3563 featuresmask |= palette_featureflags[skindata[i]];
3565 skinframe->hasalpha = false;
3568 skinframe->hasalpha = true;
3569 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3570 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3571 skinframe->qgeneratemerged = true;
3572 skinframe->qgeneratebase = skinframe->qhascolormapping;
3573 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3575 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3576 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3581 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3585 unsigned char *skindata;
3588 if (!skinframe->qpixels)
3591 if (!skinframe->qhascolormapping)
3592 colormapped = false;
3596 if (!skinframe->qgeneratebase)
3601 if (!skinframe->qgeneratemerged)
3605 width = skinframe->qwidth;
3606 height = skinframe->qheight;
3607 skindata = skinframe->qpixels;
3609 if (skinframe->qgeneratenmap)
3611 unsigned char *a, *b;
3612 skinframe->qgeneratenmap = false;
3613 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3614 b = a + width * height * 4;
3615 // use either a custom palette or the quake palette
3616 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3617 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3618 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3622 if (skinframe->qgenerateglow)
3624 skinframe->qgenerateglow = false;
3625 if (skinframe->hasalpha) // fence textures
3626 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3628 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3633 skinframe->qgeneratebase = false;
3634 skinframe->base = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3635 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3636 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3640 skinframe->qgeneratemerged = false;
3641 if (skinframe->hasalpha) // fence textures
3642 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent);
3644 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3647 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3649 Mem_Free(skinframe->qpixels);
3650 skinframe->qpixels = NULL;
3654 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3657 skinframe_t *skinframe;
3660 if (cls.state == ca_dedicated)
3663 // if already loaded just return it, otherwise make a new skinframe
3664 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3665 if (skinframe->base)
3667 textureflags &= ~TEXF_FORCE_RELOAD;
3669 skinframe->stain = NULL;
3670 skinframe->merged = NULL;
3671 skinframe->base = NULL;
3672 skinframe->pants = NULL;
3673 skinframe->shirt = NULL;
3674 skinframe->nmap = NULL;
3675 skinframe->gloss = NULL;
3676 skinframe->glow = NULL;
3677 skinframe->fog = NULL;
3678 skinframe->reflect = NULL;
3679 skinframe->hasalpha = false;
3681 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3685 if (developer_loading.integer)
3686 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3688 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3689 if ((textureflags & TEXF_ALPHA) && alphapalette)
3691 for (i = 0;i < width * height;i++)
3693 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3695 skinframe->hasalpha = true;
3699 if (r_loadfog && skinframe->hasalpha)
3700 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3703 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3704 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3709 skinframe_t *R_SkinFrame_LoadMissing(void)
3711 skinframe_t *skinframe;
3713 if (cls.state == ca_dedicated)
3716 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3717 skinframe->stain = NULL;
3718 skinframe->merged = NULL;
3719 skinframe->base = NULL;
3720 skinframe->pants = NULL;
3721 skinframe->shirt = NULL;
3722 skinframe->nmap = NULL;
3723 skinframe->gloss = NULL;
3724 skinframe->glow = NULL;
3725 skinframe->fog = NULL;
3726 skinframe->reflect = NULL;
3727 skinframe->hasalpha = false;
3729 skinframe->avgcolor[0] = rand() / RAND_MAX;
3730 skinframe->avgcolor[1] = rand() / RAND_MAX;
3731 skinframe->avgcolor[2] = rand() / RAND_MAX;
3732 skinframe->avgcolor[3] = 1;
3737 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3740 static unsigned char pix[16][16][4];
3742 if (cls.state == ca_dedicated)
3745 // this makes a light grey/dark grey checkerboard texture
3748 for (y = 0; y < 16; y++)
3750 for (x = 0; x < 16; x++)
3752 if ((y < 8) ^ (x < 8))
3770 return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3773 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3775 skinframe_t *skinframe;
3776 if (cls.state == ca_dedicated)
3778 // if already loaded just return it, otherwise make a new skinframe
3779 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3780 if (skinframe->base)
3782 textureflags &= ~TEXF_FORCE_RELOAD;
3783 skinframe->stain = NULL;
3784 skinframe->merged = NULL;
3785 skinframe->base = NULL;
3786 skinframe->pants = NULL;
3787 skinframe->shirt = NULL;
3788 skinframe->nmap = NULL;
3789 skinframe->gloss = NULL;
3790 skinframe->glow = NULL;
3791 skinframe->fog = NULL;
3792 skinframe->reflect = NULL;
3793 skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
3794 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3797 if (developer_loading.integer)
3798 Con_Printf("loading 32bit skin \"%s\"\n", name);
3799 skinframe->base = skinframe->merged = tex;
3800 Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3804 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3805 typedef struct suffixinfo_s
3808 qboolean flipx, flipy, flipdiagonal;
3811 static suffixinfo_t suffix[3][6] =
3814 {"px", false, false, false},
3815 {"nx", false, false, false},
3816 {"py", false, false, false},
3817 {"ny", false, false, false},
3818 {"pz", false, false, false},
3819 {"nz", false, false, false}
3822 {"posx", false, false, false},
3823 {"negx", false, false, false},
3824 {"posy", false, false, false},
3825 {"negy", false, false, false},
3826 {"posz", false, false, false},
3827 {"negz", false, false, false}
3830 {"rt", true, false, true},
3831 {"lf", false, true, true},
3832 {"ft", true, true, false},
3833 {"bk", false, false, false},
3834 {"up", true, false, true},
3835 {"dn", true, false, true}
3839 static int componentorder[4] = {0, 1, 2, 3};
3841 static rtexture_t *R_LoadCubemap(const char *basename)
3843 int i, j, cubemapsize;
3844 unsigned char *cubemappixels, *image_buffer;
3845 rtexture_t *cubemaptexture;
3847 // must start 0 so the first loadimagepixels has no requested width/height
3849 cubemappixels = NULL;
3850 cubemaptexture = NULL;
3851 // keep trying different suffix groups (posx, px, rt) until one loads
3852 for (j = 0;j < 3 && !cubemappixels;j++)
3854 // load the 6 images in the suffix group
3855 for (i = 0;i < 6;i++)
3857 // generate an image name based on the base and and suffix
3858 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3860 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3862 // an image loaded, make sure width and height are equal
3863 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3865 // if this is the first image to load successfully, allocate the cubemap memory
3866 if (!cubemappixels && image_width >= 1)
3868 cubemapsize = image_width;
3869 // note this clears to black, so unavailable sides are black
3870 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3872 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3874 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3877 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3879 Mem_Free(image_buffer);
3883 // if a cubemap loaded, upload it
3886 if (developer_loading.integer)
3887 Con_Printf("loading cubemap \"%s\"\n", basename);
3889 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3890 Mem_Free(cubemappixels);
3894 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3895 if (developer_loading.integer)
3897 Con_Printf("(tried tried images ");
3898 for (j = 0;j < 3;j++)
3899 for (i = 0;i < 6;i++)
3900 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3901 Con_Print(" and was unable to find any of them).\n");
3904 return cubemaptexture;
3907 rtexture_t *R_GetCubemap(const char *basename)
3910 for (i = 0;i < r_texture_numcubemaps;i++)
3911 if (r_texture_cubemaps[i] != NULL)
3912 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3913 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3914 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3915 return r_texture_whitecube;
3916 r_texture_numcubemaps++;
3917 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3918 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3919 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3920 return r_texture_cubemaps[i]->texture;
3923 static void R_Main_FreeViewCache(void)
3925 if (r_refdef.viewcache.entityvisible)
3926 Mem_Free(r_refdef.viewcache.entityvisible);
3927 if (r_refdef.viewcache.world_pvsbits)
3928 Mem_Free(r_refdef.viewcache.world_pvsbits);
3929 if (r_refdef.viewcache.world_leafvisible)
3930 Mem_Free(r_refdef.viewcache.world_leafvisible);
3931 if (r_refdef.viewcache.world_surfacevisible)
3932 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3933 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3936 static void R_Main_ResizeViewCache(void)
3938 int numentities = r_refdef.scene.numentities;
3939 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3940 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3941 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3942 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3943 if (r_refdef.viewcache.maxentities < numentities)
3945 r_refdef.viewcache.maxentities = numentities;
3946 if (r_refdef.viewcache.entityvisible)
3947 Mem_Free(r_refdef.viewcache.entityvisible);
3948 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3950 if (r_refdef.viewcache.world_numclusters != numclusters)
3952 r_refdef.viewcache.world_numclusters = numclusters;
3953 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3954 if (r_refdef.viewcache.world_pvsbits)
3955 Mem_Free(r_refdef.viewcache.world_pvsbits);
3956 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3958 if (r_refdef.viewcache.world_numleafs != numleafs)
3960 r_refdef.viewcache.world_numleafs = numleafs;
3961 if (r_refdef.viewcache.world_leafvisible)
3962 Mem_Free(r_refdef.viewcache.world_leafvisible);
3963 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3965 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3967 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3968 if (r_refdef.viewcache.world_surfacevisible)
3969 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3970 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3974 extern rtexture_t *loadingscreentexture;
3975 static void gl_main_start(void)
3977 loadingscreentexture = NULL;
3978 r_texture_blanknormalmap = NULL;
3979 r_texture_white = NULL;
3980 r_texture_grey128 = NULL;
3981 r_texture_black = NULL;
3982 r_texture_whitecube = NULL;
3983 r_texture_normalizationcube = NULL;
3984 r_texture_fogattenuation = NULL;
3985 r_texture_fogheighttexture = NULL;
3986 r_texture_gammaramps = NULL;
3987 r_texture_numcubemaps = 0;
3988 r_uniformbufferalignment = 32;
3990 r_loaddds = r_texture_dds_load.integer != 0;
3991 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3993 switch(vid.renderpath)
3995 case RENDERPATH_GL20:
3996 case RENDERPATH_D3D9:
3997 case RENDERPATH_D3D10:
3998 case RENDERPATH_D3D11:
3999 case RENDERPATH_SOFT:
4000 case RENDERPATH_GLES2:
4001 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4002 Cvar_SetValueQuick(&gl_combine, 1);
4003 Cvar_SetValueQuick(&r_glsl, 1);
4004 r_loadnormalmap = true;
4007 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4008 if (vid.support.arb_uniform_buffer_object)
4009 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4012 case RENDERPATH_GL13:
4013 case RENDERPATH_GLES1:
4014 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4015 Cvar_SetValueQuick(&gl_combine, 1);
4016 Cvar_SetValueQuick(&r_glsl, 0);
4017 r_loadnormalmap = false;
4018 r_loadgloss = false;
4021 case RENDERPATH_GL11:
4022 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4023 Cvar_SetValueQuick(&gl_combine, 0);
4024 Cvar_SetValueQuick(&r_glsl, 0);
4025 r_loadnormalmap = false;
4026 r_loadgloss = false;
4032 R_FrameData_Reset();
4033 R_BufferData_Reset();
4037 memset(r_queries, 0, sizeof(r_queries));
4039 r_qwskincache = NULL;
4040 r_qwskincache_size = 0;
4042 // due to caching of texture_t references, the collision cache must be reset
4043 Collision_Cache_Reset(true);
4045 // set up r_skinframe loading system for textures
4046 memset(&r_skinframe, 0, sizeof(r_skinframe));
4047 r_skinframe.loadsequence = 1;
4048 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4050 r_main_texturepool = R_AllocTexturePool();
4051 R_BuildBlankTextures();
4053 if (vid.support.arb_texture_cube_map)
4056 R_BuildNormalizationCube();
4058 r_texture_fogattenuation = NULL;
4059 r_texture_fogheighttexture = NULL;
4060 r_texture_gammaramps = NULL;
4061 //r_texture_fogintensity = NULL;
4062 memset(&r_fb, 0, sizeof(r_fb));
4063 Mem_ExpandableArray_NewArray(&r_fb.rendertargets, r_main_mempool, sizeof(r_rendertarget_t), 128);
4064 r_glsl_permutation = NULL;
4065 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4066 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4068 r_hlsl_permutation = NULL;
4069 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4070 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4072 memset(&r_svbsp, 0, sizeof (r_svbsp));
4074 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4075 r_texture_numcubemaps = 0;
4077 r_refdef.fogmasktable_density = 0;
4080 // For Steelstorm Android
4081 // FIXME CACHE the program and reload
4082 // FIXME see possible combinations for SS:BR android
4083 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4084 R_SetupShader_SetPermutationGLSL(0, 12);
4085 R_SetupShader_SetPermutationGLSL(0, 13);
4086 R_SetupShader_SetPermutationGLSL(0, 8388621);
4087 R_SetupShader_SetPermutationGLSL(3, 0);
4088 R_SetupShader_SetPermutationGLSL(3, 2048);
4089 R_SetupShader_SetPermutationGLSL(5, 0);
4090 R_SetupShader_SetPermutationGLSL(5, 2);
4091 R_SetupShader_SetPermutationGLSL(5, 2048);
4092 R_SetupShader_SetPermutationGLSL(5, 8388608);
4093 R_SetupShader_SetPermutationGLSL(11, 1);
4094 R_SetupShader_SetPermutationGLSL(11, 2049);
4095 R_SetupShader_SetPermutationGLSL(11, 8193);
4096 R_SetupShader_SetPermutationGLSL(11, 10241);
4097 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4101 static void gl_main_shutdown(void)
4103 R_RenderTarget_FreeUnused(true);
4104 Mem_ExpandableArray_FreeArray(&r_fb.rendertargets);
4106 R_FrameData_Reset();
4107 R_BufferData_Reset();
4109 R_Main_FreeViewCache();
4111 switch(vid.renderpath)
4113 case RENDERPATH_GL11:
4114 case RENDERPATH_GL13:
4115 case RENDERPATH_GL20:
4116 case RENDERPATH_GLES1:
4117 case RENDERPATH_GLES2:
4118 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4120 qglDeleteQueriesARB(r_maxqueries, r_queries);
4123 case RENDERPATH_D3D9:
4124 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4126 case RENDERPATH_D3D10:
4127 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4129 case RENDERPATH_D3D11:
4130 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4132 case RENDERPATH_SOFT:
4138 memset(r_queries, 0, sizeof(r_queries));
4140 r_qwskincache = NULL;
4141 r_qwskincache_size = 0;
4143 // clear out the r_skinframe state
4144 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4145 memset(&r_skinframe, 0, sizeof(r_skinframe));
4148 Mem_Free(r_svbsp.nodes);
4149 memset(&r_svbsp, 0, sizeof (r_svbsp));
4150 R_FreeTexturePool(&r_main_texturepool);
4151 loadingscreentexture = NULL;
4152 r_texture_blanknormalmap = NULL;
4153 r_texture_white = NULL;
4154 r_texture_grey128 = NULL;
4155 r_texture_black = NULL;
4156 r_texture_whitecube = NULL;
4157 r_texture_normalizationcube = NULL;
4158 r_texture_fogattenuation = NULL;
4159 r_texture_fogheighttexture = NULL;
4160 r_texture_gammaramps = NULL;
4161 r_texture_numcubemaps = 0;
4162 //r_texture_fogintensity = NULL;
4163 memset(&r_fb, 0, sizeof(r_fb));
4166 r_glsl_permutation = NULL;
4167 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4168 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4170 r_hlsl_permutation = NULL;
4171 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4172 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4176 static void gl_main_newmap(void)
4178 // FIXME: move this code to client
4179 char *entities, entname[MAX_QPATH];
4181 Mem_Free(r_qwskincache);
4182 r_qwskincache = NULL;
4183 r_qwskincache_size = 0;
4186 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4187 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4189 CL_ParseEntityLump(entities);
4193 if (cl.worldmodel->brush.entities)
4194 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4196 R_Main_FreeViewCache();
4198 R_FrameData_Reset();
4199 R_BufferData_Reset();
4202 void GL_Main_Init(void)
4205 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4206 R_InitShaderModeInfo();
4208 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4209 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4210 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4211 if (gamemode == GAME_NEHAHRA)
4213 Cvar_RegisterVariable (&gl_fogenable);
4214 Cvar_RegisterVariable (&gl_fogdensity);
4215 Cvar_RegisterVariable (&gl_fogred);
4216 Cvar_RegisterVariable (&gl_foggreen);
4217 Cvar_RegisterVariable (&gl_fogblue);
4218 Cvar_RegisterVariable (&gl_fogstart);
4219 Cvar_RegisterVariable (&gl_fogend);
4220 Cvar_RegisterVariable (&gl_skyclip);
4222 Cvar_RegisterVariable(&r_motionblur);
4223 Cvar_RegisterVariable(&r_damageblur);
4224 Cvar_RegisterVariable(&r_motionblur_averaging);
4225 Cvar_RegisterVariable(&r_motionblur_randomize);
4226 Cvar_RegisterVariable(&r_motionblur_minblur);
4227 Cvar_RegisterVariable(&r_motionblur_maxblur);
4228 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4229 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4230 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4231 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4232 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4233 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4234 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4235 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4236 Cvar_RegisterVariable(&r_equalize_entities_by);
4237 Cvar_RegisterVariable(&r_equalize_entities_to);
4238 Cvar_RegisterVariable(&r_depthfirst);
4239 Cvar_RegisterVariable(&r_useinfinitefarclip);
4240 Cvar_RegisterVariable(&r_farclip_base);
4241 Cvar_RegisterVariable(&r_farclip_world);
4242 Cvar_RegisterVariable(&r_nearclip);
4243 Cvar_RegisterVariable(&r_deformvertexes);
4244 Cvar_RegisterVariable(&r_transparent);
4245 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4246 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4247 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4248 Cvar_RegisterVariable(&r_showoverdraw);
4249 Cvar_RegisterVariable(&r_showbboxes);
4250 Cvar_RegisterVariable(&r_showbboxes_client);
4251 Cvar_RegisterVariable(&r_showsurfaces);
4252 Cvar_RegisterVariable(&r_showtris);
4253 Cvar_RegisterVariable(&r_shownormals);
4254 Cvar_RegisterVariable(&r_showlighting);
4255 Cvar_RegisterVariable(&r_showshadowvolumes);
4256 Cvar_RegisterVariable(&r_showcollisionbrushes);
4257 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4258 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4259 Cvar_RegisterVariable(&r_showdisabledepthtest);
4260 Cvar_RegisterVariable(&r_drawportals);
4261 Cvar_RegisterVariable(&r_drawentities);
4262 Cvar_RegisterVariable(&r_draw2d);
4263 Cvar_RegisterVariable(&r_drawworld);
4264 Cvar_RegisterVariable(&r_cullentities_trace);
4265 Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4266 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4267 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4268 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4269 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4270 Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4271 Cvar_RegisterVariable(&r_sortentities);
4272 Cvar_RegisterVariable(&r_drawviewmodel);
4273 Cvar_RegisterVariable(&r_drawexteriormodel);
4274 Cvar_RegisterVariable(&r_speeds);
4275 Cvar_RegisterVariable(&r_fullbrights);
4276 Cvar_RegisterVariable(&r_wateralpha);
4277 Cvar_RegisterVariable(&r_dynamic);
4278 Cvar_RegisterVariable(&r_fakelight);
4279 Cvar_RegisterVariable(&r_fakelight_intensity);
4280 Cvar_RegisterVariable(&r_fullbright_directed);
4281 Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4282 Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4283 Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4284 Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4285 Cvar_RegisterVariable(&r_fullbright);
4286 Cvar_RegisterVariable(&r_shadows);
4287 Cvar_RegisterVariable(&r_shadows_darken);
4288 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4289 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4290 Cvar_RegisterVariable(&r_shadows_throwdistance);
4291 Cvar_RegisterVariable(&r_shadows_throwdirection);
4292 Cvar_RegisterVariable(&r_shadows_focus);
4293 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4294 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4295 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4296 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4297 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4298 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4299 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4300 Cvar_RegisterVariable(&r_fog_exp2);
4301 Cvar_RegisterVariable(&r_fog_clear);
4302 Cvar_RegisterVariable(&r_drawfog);
4303 Cvar_RegisterVariable(&r_transparentdepthmasking);
4304 Cvar_RegisterVariable(&r_transparent_sortmindist);
4305 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4306 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4307 Cvar_RegisterVariable(&r_texture_dds_load);
4308 Cvar_RegisterVariable(&r_texture_dds_save);
4309 Cvar_RegisterVariable(&r_textureunits);
4310 Cvar_RegisterVariable(&gl_combine);
4311 Cvar_RegisterVariable(&r_usedepthtextures);
4312 Cvar_RegisterVariable(&r_viewfbo);
4313 Cvar_RegisterVariable(&r_rendertarget_debug);
4314 Cvar_RegisterVariable(&r_viewscale);
4315 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4316 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4317 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4318 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4319 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4320 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4321 Cvar_RegisterVariable(&r_glsl);
4322 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4323 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4324 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4325 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4326 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4327 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4328 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4329 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4330 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4331 Cvar_RegisterVariable(&r_glsl_postprocess);
4332 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4333 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4334 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4335 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4336 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4337 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4338 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4339 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4340 Cvar_RegisterVariable(&r_celshading);
4341 Cvar_RegisterVariable(&r_celoutlines);
4343 Cvar_RegisterVariable(&r_water);
4344 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4345 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4346 Cvar_RegisterVariable(&r_water_clippingplanebias);
4347 Cvar_RegisterVariable(&r_water_refractdistort);
4348 Cvar_RegisterVariable(&r_water_reflectdistort);
4349 Cvar_RegisterVariable(&r_water_scissormode);
4350 Cvar_RegisterVariable(&r_water_lowquality);
4351 Cvar_RegisterVariable(&r_water_hideplayer);
4353 Cvar_RegisterVariable(&r_lerpsprites);
4354 Cvar_RegisterVariable(&r_lerpmodels);
4355 Cvar_RegisterVariable(&r_lerplightstyles);
4356 Cvar_RegisterVariable(&r_waterscroll);
4357 Cvar_RegisterVariable(&r_bloom);
4358 Cvar_RegisterVariable(&r_bloom_colorscale);
4359 Cvar_RegisterVariable(&r_bloom_brighten);
4360 Cvar_RegisterVariable(&r_bloom_blur);
4361 Cvar_RegisterVariable(&r_bloom_resolution);
4362 Cvar_RegisterVariable(&r_bloom_colorexponent);
4363 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4364 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4365 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4366 Cvar_RegisterVariable(&r_hdr_glowintensity);
4367 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4368 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4369 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4370 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4371 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4372 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4373 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4374 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4375 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4376 Cvar_RegisterVariable(&developer_texturelogging);
4377 Cvar_RegisterVariable(&gl_lightmaps);
4378 Cvar_RegisterVariable(&r_test);
4379 Cvar_RegisterVariable(&r_batch_multidraw);
4380 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4381 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4382 Cvar_RegisterVariable(&r_glsl_skeletal);
4383 Cvar_RegisterVariable(&r_glsl_saturation);
4384 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4385 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4386 Cvar_RegisterVariable(&r_framedatasize);
4387 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4388 Cvar_RegisterVariable(&r_buffermegs[i]);
4389 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4390 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4391 Cvar_SetValue("r_fullbrights", 0);
4392 #ifdef DP_MOBILETOUCH
4393 // GLES devices have terrible depth precision in general, so...
4394 Cvar_SetValueQuick(&r_nearclip, 4);
4395 Cvar_SetValueQuick(&r_farclip_base, 4096);
4396 Cvar_SetValueQuick(&r_farclip_world, 0);
4397 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4399 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4402 void Render_Init(void)
4415 R_LightningBeams_Init();
4425 extern char *ENGINE_EXTENSIONS;
4428 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4429 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4430 gl_version = (const char *)qglGetString(GL_VERSION);
4431 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4435 if (!gl_platformextensions)
4436 gl_platformextensions = "";
4438 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4439 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4440 Con_Printf("GL_VERSION: %s\n", gl_version);
4441 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4442 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4444 VID_CheckExtensions();
4446 // LordHavoc: report supported extensions
4448 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4450 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4453 // clear to black (loading plaque will be seen over this)
4454 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4458 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4462 if (r_trippy.integer)
4464 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4466 p = r_refdef.view.frustum + i;
4471 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4475 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4479 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4483 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4487 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4491 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4495 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4499 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4507 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4511 if (r_trippy.integer)
4513 for (i = 0;i < numplanes;i++)
4520 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4524 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4528 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4532 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4536 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4540 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4544 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4548 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4556 //==================================================================================
4558 // LordHavoc: this stores temporary data used within the same frame
4560 typedef struct r_framedata_mem_s
4562 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4563 size_t size; // how much usable space
4564 size_t current; // how much space in use
4565 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4566 size_t wantedsize; // how much space was allocated
4567 unsigned char *data; // start of real data (16byte aligned)
4571 static r_framedata_mem_t *r_framedata_mem;
4573 void R_FrameData_Reset(void)
4575 while (r_framedata_mem)
4577 r_framedata_mem_t *next = r_framedata_mem->purge;
4578 Mem_Free(r_framedata_mem);
4579 r_framedata_mem = next;
4583 static void R_FrameData_Resize(qboolean mustgrow)
4586 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4587 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4588 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4590 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4591 newmem->wantedsize = wantedsize;
4592 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4593 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4594 newmem->current = 0;
4596 newmem->purge = r_framedata_mem;
4597 r_framedata_mem = newmem;
4601 void R_FrameData_NewFrame(void)
4603 R_FrameData_Resize(false);
4604 if (!r_framedata_mem)
4606 // if we ran out of space on the last frame, free the old memory now
4607 while (r_framedata_mem->purge)
4609 // repeatedly remove the second item in the list, leaving only head
4610 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4611 Mem_Free(r_framedata_mem->purge);
4612 r_framedata_mem->purge = next;
4614 // reset the current mem pointer
4615 r_framedata_mem->current = 0;
4616 r_framedata_mem->mark = 0;
4619 void *R_FrameData_Alloc(size_t size)
4624 // align to 16 byte boundary - the data pointer is already aligned, so we
4625 // only need to ensure the size of every allocation is also aligned
4626 size = (size + 15) & ~15;
4628 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4630 // emergency - we ran out of space, allocate more memory
4631 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4632 newvalue = r_framedatasize.value * 2.0f;
4633 // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
4634 if (sizeof(size_t) >= 8)
4635 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4637 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4638 // this might not be a growing it, but we'll allocate another buffer every time
4639 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4640 R_FrameData_Resize(true);
4643 data = r_framedata_mem->data + r_framedata_mem->current;
4644 r_framedata_mem->current += size;
4646 // count the usage for stats
4647 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4648 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4650 return (void *)data;
4653 void *R_FrameData_Store(size_t size, void *data)
4655 void *d = R_FrameData_Alloc(size);
4657 memcpy(d, data, size);
4661 void R_FrameData_SetMark(void)
4663 if (!r_framedata_mem)
4665 r_framedata_mem->mark = r_framedata_mem->current;
4668 void R_FrameData_ReturnToMark(void)
4670 if (!r_framedata_mem)
4672 r_framedata_mem->current = r_framedata_mem->mark;
4675 //==================================================================================
4677 // avoid reusing the same buffer objects on consecutive frames
4678 #define R_BUFFERDATA_CYCLE 3
4680 typedef struct r_bufferdata_buffer_s
4682 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4683 size_t size; // how much usable space
4684 size_t current; // how much space in use
4685 r_meshbuffer_t *buffer; // the buffer itself
4687 r_bufferdata_buffer_t;
4689 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4690 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4692 /// frees all dynamic buffers
4693 void R_BufferData_Reset(void)
4696 r_bufferdata_buffer_t **p, *mem;
4697 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4699 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4702 p = &r_bufferdata_buffer[cycle][type];
4708 R_Mesh_DestroyMeshBuffer(mem->buffer);
4715 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4716 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4718 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4720 float newvalue = r_buffermegs[type].value;
4722 // increase the cvar if we have to (but only if we already have a mem)
4723 if (mustgrow && mem)
4725 newvalue = bound(0.25f, newvalue, 256.0f);
4726 while (newvalue * 1024*1024 < minsize)
4729 // clamp the cvar to valid range
4730 newvalue = bound(0.25f, newvalue, 256.0f);
4731 if (r_buffermegs[type].value != newvalue)
4732 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4734 // calculate size in bytes
4735 size = (size_t)(newvalue * 1024*1024);
4736 size = bound(131072, size, 256*1024*1024);
4738 // allocate a new buffer if the size is different (purge old one later)
4739 // or if we were told we must grow the buffer
4740 if (!mem || mem->size != size || mustgrow)
4742 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4745 if (type == R_BUFFERDATA_VERTEX)
4746 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4747 else if (type == R_BUFFERDATA_INDEX16)
4748 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4749 else if (type == R_BUFFERDATA_INDEX32)
4750 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4751 else if (type == R_BUFFERDATA_UNIFORM)
4752 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4753 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4754 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4758 void R_BufferData_NewFrame(void)
4761 r_bufferdata_buffer_t **p, *mem;
4762 // cycle to the next frame's buffers
4763 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4764 // if we ran out of space on the last time we used these buffers, free the old memory now
4765 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4767 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4769 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4770 // free all but the head buffer, this is how we recycle obsolete
4771 // buffers after they are no longer in use
4772 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4778 R_Mesh_DestroyMeshBuffer(mem->buffer);
4781 // reset the current offset
4782 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4787 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4789 r_bufferdata_buffer_t *mem;
4793 *returnbufferoffset = 0;
4795 // align size to a byte boundary appropriate for the buffer type, this
4796 // makes all allocations have aligned start offsets
4797 if (type == R_BUFFERDATA_UNIFORM)
4798 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4800 padsize = (datasize + 15) & ~15;
4802 // if we ran out of space in this buffer we must allocate a new one
4803 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4804 R_BufferData_Resize(type, true, padsize);
4806 // if the resize did not give us enough memory, fail
4807 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4808 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4810 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4811 offset = (int)mem->current;
4812 mem->current += padsize;
4814 // upload the data to the buffer at the chosen offset
4816 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4817 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4819 // count the usage for stats
4820 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4821 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4823 // return the buffer offset
4824 *returnbufferoffset = offset;
4829 //==================================================================================
4831 // LordHavoc: animcache originally written by Echon, rewritten since then
4834 * Animation cache prevents re-generating mesh data for an animated model
4835 * multiple times in one frame for lighting, shadowing, reflections, etc.
4838 void R_AnimCache_Free(void)
4842 void R_AnimCache_ClearCache(void)
4845 entity_render_t *ent;
4847 for (i = 0;i < r_refdef.scene.numentities;i++)
4849 ent = r_refdef.scene.entities[i];
4850 ent->animcache_vertex3f = NULL;
4851 ent->animcache_vertex3f_vertexbuffer = NULL;
4852 ent->animcache_vertex3f_bufferoffset = 0;
4853 ent->animcache_normal3f = NULL;
4854 ent->animcache_normal3f_vertexbuffer = NULL;
4855 ent->animcache_normal3f_bufferoffset = 0;
4856 ent->animcache_svector3f = NULL;
4857 ent->animcache_svector3f_vertexbuffer = NULL;
4858 ent->animcache_svector3f_bufferoffset = 0;
4859 ent->animcache_tvector3f = NULL;
4860 ent->animcache_tvector3f_vertexbuffer = NULL;
4861 ent->animcache_tvector3f_bufferoffset = 0;
4862 ent->animcache_vertexmesh = NULL;
4863 ent->animcache_vertexmesh_vertexbuffer = NULL;
4864 ent->animcache_vertexmesh_bufferoffset = 0;
4865 ent->animcache_skeletaltransform3x4 = NULL;
4866 ent->animcache_skeletaltransform3x4buffer = NULL;
4867 ent->animcache_skeletaltransform3x4offset = 0;
4868 ent->animcache_skeletaltransform3x4size = 0;
4872 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4876 // check if we need the meshbuffers
4877 if (!vid.useinterleavedarrays)
4880 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4881 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4882 // TODO: upload vertexbuffer?
4883 if (ent->animcache_vertexmesh)
4885 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4886 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4887 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4888 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4889 for (i = 0;i < numvertices;i++)
4890 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4891 if (ent->animcache_svector3f)
4892 for (i = 0;i < numvertices;i++)
4893 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4894 if (ent->animcache_tvector3f)
4895 for (i = 0;i < numvertices;i++)
4896 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4897 if (ent->animcache_normal3f)
4898 for (i = 0;i < numvertices;i++)
4899 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4903 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4905 dp_model_t *model = ent->model;
4908 // see if this ent is worth caching
4909 if (!model || !model->Draw || !model->AnimateVertices)
4911 // nothing to cache if it contains no animations and has no skeleton
4912 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4914 // see if it is already cached for gpuskeletal
4915 if (ent->animcache_skeletaltransform3x4)
4917 // see if it is already cached as a mesh
4918 if (ent->animcache_vertex3f)
4920 // check if we need to add normals or tangents
4921 if (ent->animcache_normal3f)
4922 wantnormals = false;
4923 if (ent->animcache_svector3f)
4924 wanttangents = false;
4925 if (!wantnormals && !wanttangents)
4929 // check which kind of cache we need to generate
4930 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4932 // cache the skeleton so the vertex shader can use it
4933 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4934 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4935 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4936 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4937 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4938 // note: this can fail if the buffer is at the grow limit
4939 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4940 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4942 else if (ent->animcache_vertex3f)
4944 // mesh was already cached but we may need to add normals/tangents
4945 // (this only happens with multiple views, reflections, cameras, etc)
4946 if (wantnormals || wanttangents)
4948 numvertices = model->surfmesh.num_vertices;
4950 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4953 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4954 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4956 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4957 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4958 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4959 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4960 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4965 // generate mesh cache
4966 numvertices = model->surfmesh.num_vertices;
4967 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4969 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4972 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4973 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4975 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4976 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4977 if (wantnormals || wanttangents)
4979 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4980 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4981 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4983 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4984 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4985 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4990 void R_AnimCache_CacheVisibleEntities(void)
4993 qboolean wantnormals = true;
4994 qboolean wanttangents = !r_showsurfaces.integer;
4996 switch(vid.renderpath)
4998 case RENDERPATH_GL20:
4999 case RENDERPATH_D3D9:
5000 case RENDERPATH_D3D10:
5001 case RENDERPATH_D3D11:
5002 case RENDERPATH_GLES2:
5004 case RENDERPATH_GL11:
5005 case RENDERPATH_GL13:
5006 case RENDERPATH_GLES1:
5007 wanttangents = false;
5009 case RENDERPATH_SOFT:
5013 if (r_shownormals.integer)
5014 wanttangents = wantnormals = true;
5016 // TODO: thread this
5017 // NOTE: R_PrepareRTLights() also caches entities
5019 for (i = 0;i < r_refdef.scene.numentities;i++)
5020 if (r_refdef.viewcache.entityvisible[i])
5021 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5024 //==================================================================================
5026 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5029 vec3_t eyemins, eyemaxs;
5030 vec3_t boxmins, boxmaxs;
5033 dp_model_t *model = r_refdef.scene.worldmodel;
5034 static vec3_t positions[] = {
5035 { 0.5f, 0.5f, 0.5f },
5036 { 0.0f, 0.0f, 0.0f },
5037 { 0.0f, 0.0f, 1.0f },
5038 { 0.0f, 1.0f, 0.0f },
5039 { 0.0f, 1.0f, 1.0f },
5040 { 1.0f, 0.0f, 0.0f },
5041 { 1.0f, 0.0f, 1.0f },
5042 { 1.0f, 1.0f, 0.0f },
5043 { 1.0f, 1.0f, 1.0f },
5046 // sample count can be set to -1 to skip this logic, for flicker-prone objects
5050 // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5051 if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5054 if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5057 // expand the eye box a little
5058 eyemins[0] = eye[0] - eyejitter;
5059 eyemaxs[0] = eye[0] + eyejitter;
5060 eyemins[1] = eye[1] - eyejitter;
5061 eyemaxs[1] = eye[1] + eyejitter;
5062 eyemins[2] = eye[2] - eyejitter;
5063 eyemaxs[2] = eye[2] + eyejitter;
5064 // expand the box a little
5065 boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5066 boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5067 boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5068 boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5069 boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5070 boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5072 // return true if eye overlaps enlarged box
5073 if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5076 // try specific positions in the box first - note that these can be cached
5077 if (r_cullentities_trace_entityocclusion.integer)
5079 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5081 VectorCopy(eye, start);
5082 end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5083 end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5084 end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5085 //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5086 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5087 // not picky - if the trace ended anywhere in the box we're good
5088 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5092 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5095 // try various random positions
5096 for (i = 0; i < numsamples; i++)
5098 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5099 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5100 if (r_cullentities_trace_entityocclusion.integer)
5102 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5103 // not picky - if the trace ended anywhere in the box we're good
5104 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5107 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5115 static void R_View_UpdateEntityVisible (void)
5120 entity_render_t *ent;
5122 if (r_refdef.envmap || r_fb.water.hideplayer)
5123 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5124 else if (chase_active.integer || r_fb.water.renderingscene)
5125 renderimask = RENDER_VIEWMODEL;
5127 renderimask = RENDER_EXTERIORMODEL;
5128 if (!r_drawviewmodel.integer)
5129 renderimask |= RENDER_VIEWMODEL;
5130 if (!r_drawexteriormodel.integer)
5131 renderimask |= RENDER_EXTERIORMODEL;
5132 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5133 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5135 // worldmodel can check visibility
5136 for (i = 0;i < r_refdef.scene.numentities;i++)
5138 ent = r_refdef.scene.entities[i];
5139 if (!(ent->flags & renderimask))
5140 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
5141 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
5142 r_refdef.viewcache.entityvisible[i] = true;
5147 // no worldmodel or it can't check visibility
5148 for (i = 0;i < r_refdef.scene.numentities;i++)
5150 ent = r_refdef.scene.entities[i];
5151 if (!(ent->flags & renderimask))
5152 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
5153 r_refdef.viewcache.entityvisible[i] = true;
5156 if (r_cullentities_trace.integer)
5158 for (i = 0;i < r_refdef.scene.numentities;i++)
5160 if (!r_refdef.viewcache.entityvisible[i])
5162 ent = r_refdef.scene.entities[i];
5163 if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5165 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5166 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5167 ent->last_trace_visibility = realtime;
5168 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5169 r_refdef.viewcache.entityvisible[i] = 0;
5175 /// only used if skyrendermasked, and normally returns false
5176 static int R_DrawBrushModelsSky (void)
5179 entity_render_t *ent;
5182 for (i = 0;i < r_refdef.scene.numentities;i++)
5184 if (!r_refdef.viewcache.entityvisible[i])
5186 ent = r_refdef.scene.entities[i];
5187 if (!ent->model || !ent->model->DrawSky)
5189 ent->model->DrawSky(ent);
5195 static void R_DrawNoModel(entity_render_t *ent);
5196 static void R_DrawModels(void)
5199 entity_render_t *ent;
5201 for (i = 0;i < r_refdef.scene.numentities;i++)
5203 if (!r_refdef.viewcache.entityvisible[i])
5205 ent = r_refdef.scene.entities[i];
5206 r_refdef.stats[r_stat_entities]++;
5208 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5211 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5212 Con_Printf("R_DrawModels\n");
5213 Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
5214 Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
5215 Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
5218 if (ent->model && ent->model->Draw != NULL)
5219 ent->model->Draw(ent);
5225 static void R_DrawModelsDepth(void)
5228 entity_render_t *ent;
5230 for (i = 0;i < r_refdef.scene.numentities;i++)
5232 if (!r_refdef.viewcache.entityvisible[i])
5234 ent = r_refdef.scene.entities[i];
5235 if (ent->model && ent->model->DrawDepth != NULL)
5236 ent->model->DrawDepth(ent);
5240 static void R_DrawModelsDebug(void)
5243 entity_render_t *ent;
5245 for (i = 0;i < r_refdef.scene.numentities;i++)
5247 if (!r_refdef.viewcache.entityvisible[i])
5249 ent = r_refdef.scene.entities[i];
5250 if (ent->model && ent->model->DrawDebug != NULL)
5251 ent->model->DrawDebug(ent);
5255 static void R_DrawModelsAddWaterPlanes(void)
5258 entity_render_t *ent;
5260 for (i = 0;i < r_refdef.scene.numentities;i++)
5262 if (!r_refdef.viewcache.entityvisible[i])
5264 ent = r_refdef.scene.entities[i];
5265 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5266 ent->model->DrawAddWaterPlanes(ent);
5270 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5272 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5274 if (r_hdr_irisadaptation.integer)
5279 vec3_t diffusenormal;
5281 vec_t brightness = 0.0f;
5286 VectorCopy(r_refdef.view.forward, forward);
5287 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5289 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5290 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5291 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5292 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5293 d = DotProduct(forward, diffusenormal);
5294 brightness += VectorLength(ambient);
5296 brightness += d * VectorLength(diffuse);
5298 brightness *= 1.0f / c;
5299 brightness += 0.00001f; // make sure it's never zero
5300 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5301 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5302 current = r_hdr_irisadaptation_value.value;
5304 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5305 else if (current > goal)
5306 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5307 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5308 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5310 else if (r_hdr_irisadaptation_value.value != 1.0f)
5311 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5314 static void R_View_SetFrustum(const int *scissor)
5317 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5318 vec3_t forward, left, up, origin, v;
5322 // flipped x coordinates (because x points left here)
5323 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5324 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5326 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5327 switch(vid.renderpath)
5329 case RENDERPATH_D3D9:
5330 case RENDERPATH_D3D10:
5331 case RENDERPATH_D3D11:
5332 // non-flipped y coordinates
5333 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5334 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5336 case RENDERPATH_SOFT:
5337 case RENDERPATH_GL11:
5338 case RENDERPATH_GL13:
5339 case RENDERPATH_GL20:
5340 case RENDERPATH_GLES1:
5341 case RENDERPATH_GLES2:
5342 // non-flipped y coordinates
5343 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5344 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5349 // we can't trust r_refdef.view.forward and friends in reflected scenes
5350 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5353 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5354 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5355 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5356 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5357 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5358 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5359 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5360 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5361 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5362 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5363 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5364 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5368 zNear = r_refdef.nearclip;
5369 nudge = 1.0 - 1.0 / (1<<23);
5370 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5371 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5372 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5373 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5374 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5375 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5376 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5377 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5383 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5384 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5385 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5386 r_refdef.view.frustum[0].dist = m[15] - m[12];
5388 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5389 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5390 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5391 r_refdef.view.frustum[1].dist = m[15] + m[12];
5393 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5394 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5395 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5396 r_refdef.view.frustum[2].dist = m[15] - m[13];
5398 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5399 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5400 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5401 r_refdef.view.frustum[3].dist = m[15] + m[13];
5403 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5404 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5405 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5406 r_refdef.view.frustum[4].dist = m[15] - m[14];
5408 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5409 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5410 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5411 r_refdef.view.frustum[5].dist = m[15] + m[14];
5414 if (r_refdef.view.useperspective)
5416 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5417 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5418 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5419 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5420 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5422 // then the normals from the corners relative to origin
5423 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5424 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5425 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5426 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5428 // in a NORMAL view, forward cross left == up
5429 // in a REFLECTED view, forward cross left == down
5430 // so our cross products above need to be adjusted for a left handed coordinate system
5431 CrossProduct(forward, left, v);
5432 if(DotProduct(v, up) < 0)
5434 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5435 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5436 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5437 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5440 // Leaving those out was a mistake, those were in the old code, and they
5441 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5442 // I couldn't reproduce it after adding those normalizations. --blub
5443 VectorNormalize(r_refdef.view.frustum[0].normal);
5444 VectorNormalize(r_refdef.view.frustum[1].normal);
5445 VectorNormalize(r_refdef.view.frustum[2].normal);
5446 VectorNormalize(r_refdef.view.frustum[3].normal);
5448 // make the corners absolute
5449 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5450 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5451 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5452 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5455 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5457 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5458 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5459 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5460 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5461 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5465 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5466 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5467 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5468 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5469 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5470 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5471 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5472 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5473 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5474 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5476 r_refdef.view.numfrustumplanes = 5;
5478 if (r_refdef.view.useclipplane)
5480 r_refdef.view.numfrustumplanes = 6;
5481 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5484 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5485 PlaneClassify(r_refdef.view.frustum + i);
5487 // LordHavoc: note to all quake engine coders, Quake had a special case
5488 // for 90 degrees which assumed a square view (wrong), so I removed it,
5489 // Quake2 has it disabled as well.
5491 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5492 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5493 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5494 //PlaneClassify(&frustum[0]);
5496 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5497 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5498 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5499 //PlaneClassify(&frustum[1]);
5501 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5502 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5503 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5504 //PlaneClassify(&frustum[2]);
5506 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5507 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5508 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5509 //PlaneClassify(&frustum[3]);
5512 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5513 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5514 //PlaneClassify(&frustum[4]);
5517 static void R_View_UpdateWithScissor(const int *myscissor)
5519 R_Main_ResizeViewCache();
5520 R_View_SetFrustum(myscissor);
5521 R_View_WorldVisibility(r_refdef.view.useclipplane);
5522 R_View_UpdateEntityVisible();
5525 static void R_View_Update(void)
5527 R_Main_ResizeViewCache();
5528 R_View_SetFrustum(NULL);
5529 R_View_WorldVisibility(r_refdef.view.useclipplane);
5530 R_View_UpdateEntityVisible();
5533 float viewscalefpsadjusted = 1.0f;
5535 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5537 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5538 scale = bound(0.03125f, scale, 1.0f);
5539 *outwidth = (int)ceil(width * scale);
5540 *outheight = (int)ceil(height * scale);
5543 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5545 const float *customclipplane = NULL;
5547 int /*rtwidth,*/ rtheight;
5548 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5550 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
5551 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5552 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5553 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5554 dist = r_refdef.view.clipplane.dist;
5555 plane[0] = r_refdef.view.clipplane.normal[0];
5556 plane[1] = r_refdef.view.clipplane.normal[1];
5557 plane[2] = r_refdef.view.clipplane.normal[2];
5559 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5562 //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
5563 rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
5565 if (!r_refdef.view.useperspective)
5566 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, -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, customclipplane);
5567 else if (vid.stencil && r_useinfinitefarclip.integer)
5568 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5570 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5571 R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5572 R_SetViewport(&r_refdef.view.viewport);
5573 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5575 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5576 float screenplane[4];
5577 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5578 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5579 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5580 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5581 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5585 void R_EntityMatrix(const matrix4x4_t *matrix)
5587 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5589 gl_modelmatrixchanged = false;
5590 gl_modelmatrix = *matrix;
5591 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5592 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5593 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5594 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5596 switch(vid.renderpath)
5598 case RENDERPATH_D3D9:
5600 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5601 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5604 case RENDERPATH_D3D10:
5605 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5607 case RENDERPATH_D3D11:
5608 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5610 case RENDERPATH_GL11:
5611 case RENDERPATH_GL13:
5612 case RENDERPATH_GLES1:
5614 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5617 case RENDERPATH_SOFT:
5618 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5619 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5621 case RENDERPATH_GL20:
5622 case RENDERPATH_GLES2:
5623 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5624 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5630 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
5632 r_viewport_t viewport;
5636 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5637 R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
5638 R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5639 R_SetViewport(&viewport);
5640 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5641 GL_Color(1, 1, 1, 1);
5642 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5643 GL_BlendFunc(GL_ONE, GL_ZERO);
5644 GL_ScissorTest(false);
5645 GL_DepthMask(false);
5646 GL_DepthRange(0, 1);
5647 GL_DepthTest(false);
5648 GL_DepthFunc(GL_LEQUAL);
5649 R_EntityMatrix(&identitymatrix);
5650 R_Mesh_ResetTextureState();
5651 GL_PolygonOffset(0, 0);
5652 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5653 switch(vid.renderpath)
5655 case RENDERPATH_GL11:
5656 case RENDERPATH_GL13:
5657 case RENDERPATH_GL20:
5658 case RENDERPATH_GLES1:
5659 case RENDERPATH_GLES2:
5660 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5662 case RENDERPATH_D3D9:
5663 case RENDERPATH_D3D10:
5664 case RENDERPATH_D3D11:
5665 case RENDERPATH_SOFT:
5668 GL_CullFace(GL_NONE);
5673 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5677 R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
5680 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5684 R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5685 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5686 GL_Color(1, 1, 1, 1);
5687 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5688 GL_BlendFunc(GL_ONE, GL_ZERO);
5689 GL_ScissorTest(true);
5691 GL_DepthRange(0, 1);
5693 GL_DepthFunc(GL_LEQUAL);
5694 R_EntityMatrix(&identitymatrix);
5695 R_Mesh_ResetTextureState();
5696 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5697 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5698 switch(vid.renderpath)
5700 case RENDERPATH_GL11:
5701 case RENDERPATH_GL13:
5702 case RENDERPATH_GL20:
5703 case RENDERPATH_GLES1:
5704 case RENDERPATH_GLES2:
5705 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5707 case RENDERPATH_D3D9:
5708 case RENDERPATH_D3D10:
5709 case RENDERPATH_D3D11:
5710 case RENDERPATH_SOFT:
5713 GL_CullFace(r_refdef.view.cullface_back);
5718 R_RenderView_UpdateViewVectors
5721 void R_RenderView_UpdateViewVectors(void)
5723 // break apart the view matrix into vectors for various purposes
5724 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5725 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5726 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5727 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5728 // make an inverted copy of the view matrix for tracking sprites
5729 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5732 void R_RenderTarget_FreeUnused(qboolean force)
5735 end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5736 for (i = 0; i < end; i++)
5738 r_rendertarget_t *r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5739 // free resources for rendertargets that have not been used for a while
5740 // (note: this check is run after the frame render, so any targets used
5741 // this frame will not be affected even at low framerates)
5742 if (r && (realtime - r->lastusetime > 0.2 || force))
5745 R_Mesh_DestroyFramebufferObject(r->fbo);
5746 for (j = 0; j < sizeof(r->colortexture) / sizeof(r->colortexture[0]); j++)
5747 if (r->colortexture[j])
5748 R_FreeTexture(r->colortexture[j]);
5749 if (r->depthtexture)
5750 R_FreeTexture(r->depthtexture);
5751 Mem_ExpandableArray_FreeRecord(&r_fb.rendertargets, r);
5756 static void R_CalcTexCoordsForView(float x, float y, float w, float h, float tw, float th, float *texcoord2f)
5758 float iw = 1.0f / tw, ih = 1.0f / th, x1, y1, x2, y2;
5759 switch (vid.renderpath)
5761 case RENDERPATH_D3D9:
5762 x1 = (x + 0.5f) * iw;
5763 x2 = (x + 0.5f + w) * iw;
5764 y1 = (y + 0.5f) * ih;
5765 y2 = (y + 0.5f + h) * ih;
5771 y2 = (th - y - h) * ih;
5784 r_rendertarget_t *R_RenderTarget_Get(int texturewidth, int textureheight, textype_t depthtextype, qboolean depthisrenderbuffer, textype_t colortextype0, textype_t colortextype1, textype_t colortextype2, textype_t colortextype3)
5787 r_rendertarget_t *r = NULL;
5789 // first try to reuse an existing slot if possible
5790 end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5791 for (i = 0; i < end; i++)
5793 r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5794 if (r && r->lastusetime != realtime && r->texturewidth == texturewidth && r->textureheight == textureheight && r->depthtextype == depthtextype && r->colortextype[0] == colortextype0 && r->colortextype[1] == colortextype1 && r->colortextype[2] == colortextype2 && r->colortextype[3] == colortextype3)
5799 // no unused exact match found, so we have to make one in the first unused slot
5800 r = (r_rendertarget_t *)Mem_ExpandableArray_AllocRecord(&r_fb.rendertargets);
5801 r->texturewidth = texturewidth;
5802 r->textureheight = textureheight;
5803 r->colortextype[0] = colortextype0;
5804 r->colortextype[1] = colortextype1;
5805 r->colortextype[2] = colortextype2;
5806 r->colortextype[3] = colortextype3;
5807 r->depthtextype = depthtextype;
5808 r->depthisrenderbuffer = depthisrenderbuffer;
5809 for (j = 0; j < 4; j++)
5810 if (r->colortextype[j])
5811 r->colortexture[j] = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_%i_type%i", i, j, (int)r->colortextype[j]), r->texturewidth, r->textureheight, NULL, r->colortextype[j], TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5812 if (r->depthtextype)
5814 if (r->depthisrenderbuffer)
5815 r->depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, va(vabuf, sizeof(vabuf), "renderbuffer%i_depth_type%i", i, (int)r->depthtextype), r->texturewidth, r->textureheight, r->depthtextype);
5817 r->depthtexture = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_depth_type%i", i, j, (int)r->depthtextype), r->texturewidth, r->textureheight, NULL, r->depthtextype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5819 r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
5821 r_refdef.stats[r_stat_rendertargets_used]++;
5822 r_refdef.stats[r_stat_rendertargets_pixels] += r->texturewidth * r->textureheight;
5823 r->lastusetime = realtime;
5824 R_CalcTexCoordsForView(0, 0, r->texturewidth, r->textureheight, r->texturewidth, r->textureheight, r->texcoord2f);
5828 static void R_Water_StartFrame(void)
5830 int waterwidth, waterheight;
5832 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5835 switch(vid.renderpath)
5837 case RENDERPATH_GL20:
5838 case RENDERPATH_D3D9:
5839 case RENDERPATH_D3D10:
5840 case RENDERPATH_D3D11:
5841 case RENDERPATH_SOFT:
5842 case RENDERPATH_GLES2:
5844 case RENDERPATH_GL11:
5845 case RENDERPATH_GL13:
5846 case RENDERPATH_GLES1:
5850 // set waterwidth and waterheight to the water resolution that will be
5851 // used (often less than the screen resolution for faster rendering)
5852 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5853 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5854 R_GetScaledViewSize(waterwidth, waterheight, &waterwidth, &waterheight);
5856 if (!r_water.integer || r_showsurfaces.integer)
5857 waterwidth = waterheight = 0;
5859 // set up variables that will be used in shader setup
5860 r_fb.water.waterwidth = waterwidth;
5861 r_fb.water.waterheight = waterheight;
5862 r_fb.water.texturewidth = waterwidth;
5863 r_fb.water.textureheight = waterheight;
5864 r_fb.water.camerawidth = waterwidth;
5865 r_fb.water.cameraheight = waterheight;
5866 r_fb.water.screenscale[0] = 0.5f;
5867 r_fb.water.screenscale[1] = 0.5f;
5868 r_fb.water.screencenter[0] = 0.5f;
5869 r_fb.water.screencenter[1] = 0.5f;
5870 r_fb.water.enabled = waterwidth != 0;
5872 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5873 r_fb.water.numwaterplanes = 0;
5876 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5878 int planeindex, bestplaneindex, vertexindex;
5879 vec3_t mins, maxs, normal, center, v, n;
5880 vec_t planescore, bestplanescore;
5882 r_waterstate_waterplane_t *p;
5883 texture_t *t = R_GetCurrentTexture(surface->texture);
5885 rsurface.texture = t;
5886 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5887 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5888 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5890 // average the vertex normals, find the surface bounds (after deformvertexes)
5891 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5892 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5893 VectorCopy(n, normal);
5894 VectorCopy(v, mins);
5895 VectorCopy(v, maxs);
5896 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5898 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5899 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5900 VectorAdd(normal, n, normal);
5901 mins[0] = min(mins[0], v[0]);
5902 mins[1] = min(mins[1], v[1]);
5903 mins[2] = min(mins[2], v[2]);
5904 maxs[0] = max(maxs[0], v[0]);
5905 maxs[1] = max(maxs[1], v[1]);
5906 maxs[2] = max(maxs[2], v[2]);
5908 VectorNormalize(normal);
5909 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5911 VectorCopy(normal, plane.normal);
5912 VectorNormalize(plane.normal);
5913 plane.dist = DotProduct(center, plane.normal);
5914 PlaneClassify(&plane);
5915 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5917 // skip backfaces (except if nocullface is set)
5918 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5920 VectorNegate(plane.normal, plane.normal);
5922 PlaneClassify(&plane);
5926 // find a matching plane if there is one
5927 bestplaneindex = -1;
5928 bestplanescore = 1048576.0f;
5929 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5931 if(p->camera_entity == t->camera_entity)
5933 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5934 if (bestplaneindex < 0 || bestplanescore > planescore)
5936 bestplaneindex = planeindex;
5937 bestplanescore = planescore;
5941 planeindex = bestplaneindex;
5943 // if this surface does not fit any known plane rendered this frame, add one
5944 if (planeindex < 0 || bestplanescore > 0.001f)
5946 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5948 // store the new plane
5949 planeindex = r_fb.water.numwaterplanes++;
5950 p = r_fb.water.waterplanes + planeindex;
5952 // clear materialflags and pvs
5953 p->materialflags = 0;
5954 p->pvsvalid = false;
5955 p->camera_entity = t->camera_entity;
5956 VectorCopy(mins, p->mins);
5957 VectorCopy(maxs, p->maxs);
5961 // We're totally screwed.
5967 // merge mins/maxs when we're adding this surface to the plane
5968 p = r_fb.water.waterplanes + planeindex;
5969 p->mins[0] = min(p->mins[0], mins[0]);
5970 p->mins[1] = min(p->mins[1], mins[1]);
5971 p->mins[2] = min(p->mins[2], mins[2]);
5972 p->maxs[0] = max(p->maxs[0], maxs[0]);
5973 p->maxs[1] = max(p->maxs[1], maxs[1]);
5974 p->maxs[2] = max(p->maxs[2], maxs[2]);
5976 // merge this surface's materialflags into the waterplane
5977 p->materialflags |= t->currentmaterialflags;
5978 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5980 // merge this surface's PVS into the waterplane
5981 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5982 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5984 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5990 extern cvar_t r_drawparticles;
5991 extern cvar_t r_drawdecals;
5993 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int viewx, int viewy, int viewwidth, int viewheight)
5996 r_refdef_view_t originalview;
5997 r_refdef_view_t myview;
5998 int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5999 r_waterstate_waterplane_t *p;
6001 r_rendertarget_t *rt;
6003 originalview = r_refdef.view;
6005 // lowquality hack, temporarily shut down some cvars and restore afterwards
6006 qualityreduction = r_water_lowquality.integer;
6007 if (qualityreduction > 0)
6009 if (qualityreduction >= 1)
6011 old_r_shadows = r_shadows.integer;
6012 old_r_worldrtlight = r_shadow_realtime_world.integer;
6013 old_r_dlight = r_shadow_realtime_dlight.integer;
6014 Cvar_SetValueQuick(&r_shadows, 0);
6015 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6016 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6018 if (qualityreduction >= 2)
6020 old_r_dynamic = r_dynamic.integer;
6021 old_r_particles = r_drawparticles.integer;
6022 old_r_decals = r_drawdecals.integer;
6023 Cvar_SetValueQuick(&r_dynamic, 0);
6024 Cvar_SetValueQuick(&r_drawparticles, 0);
6025 Cvar_SetValueQuick(&r_drawdecals, 0);
6029 for (planeindex = 0, p = r_fb.water.waterplanes; planeindex < r_fb.water.numwaterplanes; planeindex++, p++)
6031 p->rt_reflection = NULL;
6032 p->rt_refraction = NULL;
6033 p->rt_camera = NULL;
6037 r_refdef.view = originalview;
6038 r_refdef.view.showdebug = false;
6039 r_refdef.view.width = r_fb.water.waterwidth;
6040 r_refdef.view.height = r_fb.water.waterheight;
6041 r_refdef.view.useclipplane = true;
6042 myview = r_refdef.view;
6043 r_fb.water.renderingscene = true;
6044 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6046 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6049 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6051 rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6052 if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6054 r_refdef.view = myview;
6055 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6056 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6057 if(r_water_scissormode.integer)
6059 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6060 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6062 p->rt_reflection = NULL;
6063 p->rt_refraction = NULL;
6064 p->rt_camera = NULL;
6069 r_refdef.view.clipplane = p->plane;
6070 // reverse the cullface settings for this render
6071 r_refdef.view.cullface_front = GL_FRONT;
6072 r_refdef.view.cullface_back = GL_BACK;
6073 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6075 r_refdef.view.usecustompvs = true;
6077 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6079 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6082 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6083 R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6084 GL_ScissorTest(false);
6085 R_ClearScreen(r_refdef.fogenabled);
6086 GL_ScissorTest(true);
6087 if(r_water_scissormode.integer & 2)
6088 R_View_UpdateWithScissor(myscissor);
6091 R_AnimCache_CacheVisibleEntities();
6092 if(r_water_scissormode.integer & 1)
6093 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6094 R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6096 r_fb.water.hideplayer = false;
6097 p->rt_reflection = rt;
6100 // render the normal view scene and copy into texture
6101 // (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)
6102 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6104 rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6105 if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6107 r_refdef.view = myview;
6108 if(r_water_scissormode.integer)
6110 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6111 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6113 p->rt_reflection = NULL;
6114 p->rt_refraction = NULL;
6115 p->rt_camera = NULL;
6120 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6122 r_refdef.view.clipplane = p->plane;
6123 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6124 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6126 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6128 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6129 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6130 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6131 R_RenderView_UpdateViewVectors();
6132 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6134 r_refdef.view.usecustompvs = true;
6135 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
6139 PlaneClassify(&r_refdef.view.clipplane);
6141 R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6142 GL_ScissorTest(false);
6143 R_ClearScreen(r_refdef.fogenabled);
6144 GL_ScissorTest(true);
6145 if(r_water_scissormode.integer & 2)
6146 R_View_UpdateWithScissor(myscissor);
6149 R_AnimCache_CacheVisibleEntities();
6150 if(r_water_scissormode.integer & 1)
6151 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6152 R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6154 r_fb.water.hideplayer = false;
6155 p->rt_refraction = rt;
6157 else if (p->materialflags & MATERIALFLAG_CAMERA)
6159 rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6160 if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6162 r_refdef.view = myview;
6164 r_refdef.view.clipplane = p->plane;
6165 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6166 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6168 r_refdef.view.width = r_fb.water.camerawidth;
6169 r_refdef.view.height = r_fb.water.cameraheight;
6170 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6171 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6172 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6173 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6175 if(p->camera_entity)
6177 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6178 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6181 // note: all of the view is used for displaying... so
6182 // there is no use in scissoring
6184 // reverse the cullface settings for this render
6185 r_refdef.view.cullface_front = GL_FRONT;
6186 r_refdef.view.cullface_back = GL_BACK;
6187 // also reverse the view matrix
6188 Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
6189 R_RenderView_UpdateViewVectors();
6190 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6192 r_refdef.view.usecustompvs = true;
6193 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
6196 // camera needs no clipplane
6197 r_refdef.view.useclipplane = false;
6199 PlaneClassify(&r_refdef.view.clipplane);
6201 r_fb.water.hideplayer = false;
6203 R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6204 GL_ScissorTest(false);
6205 R_ClearScreen(r_refdef.fogenabled);
6206 GL_ScissorTest(true);
6208 R_AnimCache_CacheVisibleEntities();
6209 R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6211 r_fb.water.hideplayer = false;
6216 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6217 r_fb.water.renderingscene = false;
6218 r_refdef.view = originalview;
6219 R_ResetViewRendering3D(fbo, depthtexture, colortexture, viewx, viewy, viewwidth, viewheight);
6221 R_AnimCache_CacheVisibleEntities();
6224 r_refdef.view = originalview;
6225 r_fb.water.renderingscene = false;
6226 Cvar_SetValueQuick(&r_water, 0);
6227 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6229 // lowquality hack, restore cvars
6230 if (qualityreduction > 0)
6232 if (qualityreduction >= 1)
6234 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6235 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6236 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6238 if (qualityreduction >= 2)
6240 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6241 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6242 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6247 static void R_Bloom_StartFrame(void)
6249 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6250 int viewwidth, viewheight;
6251 textype_t textype = TEXTYPE_COLORBUFFER;
6253 // clear the pointers to rendertargets from last frame as they're stale
6254 r_fb.rt_screen = NULL;
6255 r_fb.rt_bloom = NULL;
6257 switch (vid.renderpath)
6259 case RENDERPATH_GL20:
6260 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6261 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6262 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6263 // for simplicity, bloom requires FBO render to texture, which basically all video drivers support now
6264 if (!vid.support.ext_framebuffer_object)
6267 case RENDERPATH_GL11:
6268 case RENDERPATH_GL13:
6269 case RENDERPATH_GLES1:
6270 return; // don't bother
6271 case RENDERPATH_GLES2:
6272 case RENDERPATH_D3D9:
6273 case RENDERPATH_D3D10:
6274 case RENDERPATH_D3D11:
6275 r_fb.usedepthtextures = false;
6277 case RENDERPATH_SOFT:
6278 r_fb.usedepthtextures = true;
6282 if (r_viewscale_fpsscaling.integer)
6284 double actualframetime;
6285 double targetframetime;
6287 actualframetime = r_refdef.lastdrawscreentime;
6288 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6289 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6290 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6291 if (r_viewscale_fpsscaling_stepsize.value > 0)
6292 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6293 viewscalefpsadjusted += adjust;
6294 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6297 viewscalefpsadjusted = 1.0f;
6299 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6301 // set bloomwidth and bloomheight to the bloom resolution that will be
6302 // used (often less than the screen resolution for faster rendering)
6303 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6304 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6305 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6306 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6307 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6309 // calculate desired texture sizes
6310 screentexturewidth = viewwidth;
6311 screentextureheight = viewheight;
6312 bloomtexturewidth = r_fb.bloomwidth;
6313 bloomtextureheight = r_fb.bloomheight;
6315 if ((r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6317 Cvar_SetValueQuick(&r_bloom, 0);
6318 Cvar_SetValueQuick(&r_motionblur, 0);
6319 Cvar_SetValueQuick(&r_damageblur, 0);
6322 // allocate motionblur ghost texture if needed - this is the only persistent texture and is only useful on the main view
6323 if (r_refdef.view.ismain && (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.textype != textype))
6325 if (r_fb.ghosttexture)
6326 R_FreeTexture(r_fb.ghosttexture);
6327 r_fb.ghosttexture = NULL;
6329 r_fb.screentexturewidth = screentexturewidth;
6330 r_fb.screentextureheight = screentextureheight;
6331 r_fb.textype = textype;
6333 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6335 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6336 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6337 r_fb.ghosttexture_valid = false;
6341 if (r_bloom.integer)
6343 // bloom texture is a different resolution
6344 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6345 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6346 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6349 r_fb.bloomwidth = r_fb.bloomheight = 0;
6351 r_fb.rt_screen = R_RenderTarget_Get(screentexturewidth, screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6353 r_refdef.view.clear = true;
6356 static void R_Bloom_MakeTexture(void)
6359 float xoffset, yoffset, r, brighten;
6360 float colorscale = r_bloom_colorscale.value;
6361 r_viewport_t bloomviewport;
6362 r_rendertarget_t *prev, *cur;
6363 textype_t textype = r_fb.rt_screen->colortextype[0];
6365 r_refdef.stats[r_stat_bloom]++;
6367 R_Viewport_InitOrtho(&bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6369 // scale down screen texture to the bloom texture size
6371 prev = r_fb.rt_screen;
6372 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6373 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6374 R_SetViewport(&bloomviewport);
6375 GL_CullFace(GL_NONE);
6376 GL_DepthTest(false);
6377 GL_BlendFunc(GL_ONE, GL_ZERO);
6378 GL_Color(colorscale, colorscale, colorscale, 1);
6379 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6380 // TODO: do boxfilter scale-down in shader?
6381 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, true);
6382 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6383 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6384 // we now have a properly scaled bloom image
6386 // multiply bloom image by itself as many times as desired to darken it
6387 // TODO: if people actually use this it could be done more quickly in the previous shader pass
6388 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6391 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6392 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6394 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6396 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6397 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6398 GL_Color(1,1,1,1); // no fix factor supported here
6399 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6400 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6401 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6402 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6405 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6406 brighten = r_bloom_brighten.value;
6407 brighten = sqrt(brighten);
6409 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6411 for (dir = 0;dir < 2;dir++)
6414 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6415 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6416 // blend on at multiple vertical offsets to achieve a vertical blur
6417 // TODO: do offset blends using GLSL
6418 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6419 GL_BlendFunc(GL_ONE, GL_ZERO);
6420 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6421 for (x = -range;x <= range;x++)
6423 if (!dir){xoffset = 0;yoffset = x;}
6424 else {xoffset = x;yoffset = 0;}
6425 xoffset /= (float)prev->texturewidth;
6426 yoffset /= (float)prev->textureheight;
6427 // compute a texcoord array with the specified x and y offset
6428 r_fb.offsettexcoord2f[0] = xoffset+prev->texcoord2f[0];
6429 r_fb.offsettexcoord2f[1] = yoffset+prev->texcoord2f[1];
6430 r_fb.offsettexcoord2f[2] = xoffset+prev->texcoord2f[2];
6431 r_fb.offsettexcoord2f[3] = yoffset+prev->texcoord2f[3];
6432 r_fb.offsettexcoord2f[4] = xoffset+prev->texcoord2f[4];
6433 r_fb.offsettexcoord2f[5] = yoffset+prev->texcoord2f[5];
6434 r_fb.offsettexcoord2f[6] = xoffset+prev->texcoord2f[6];
6435 r_fb.offsettexcoord2f[7] = yoffset+prev->texcoord2f[7];
6436 // this r value looks like a 'dot' particle, fading sharply to
6437 // black at the edges
6438 // (probably not realistic but looks good enough)
6439 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6440 //r = brighten/(range*2+1);
6441 r = brighten / (range * 2 + 1);
6443 r *= (1 - x*x/(float)((range+1)*(range+1)));
6446 GL_Color(r, r, r, 1);
6447 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6448 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6449 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6450 GL_BlendFunc(GL_ONE, GL_ONE);
6454 // now we have the bloom image, so keep track of it
6455 r_fb.rt_bloom = cur;
6458 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
6460 dpuint64 permutation;
6461 float uservecs[4][4];
6462 rtexture_t *viewtexture;
6463 rtexture_t *bloomtexture;
6465 R_EntityMatrix(&identitymatrix);
6467 switch (vid.renderpath)
6469 case RENDERPATH_GL20:
6470 case RENDERPATH_D3D9:
6471 case RENDERPATH_D3D10:
6472 case RENDERPATH_D3D11:
6473 case RENDERPATH_SOFT:
6474 case RENDERPATH_GLES2:
6476 (r_fb.bloomwidth ? SHADERPERMUTATION_BLOOM : 0)
6477 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6478 | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6479 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6480 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6482 if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6484 // declare variables
6485 float blur_factor, blur_mouseaccel, blur_velocity;
6486 static float blur_average;
6487 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6489 // set a goal for the factoring
6490 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6491 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6492 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6493 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6494 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6495 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6497 // from the goal, pick an averaged value between goal and last value
6498 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6499 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6501 // enforce minimum amount of blur
6502 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6504 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6506 // calculate values into a standard alpha
6507 cl.motionbluralpha = 1 - exp(-
6509 (r_motionblur.value * blur_factor / 80)
6511 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6514 max(0.0001, cl.time - cl.oldtime) // fps independent
6517 // randomization for the blur value to combat persistent ghosting
6518 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6519 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6522 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6523 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6525 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6526 GL_Color(1, 1, 1, cl.motionbluralpha);
6527 R_CalcTexCoordsForView(0, 0, viewwidth, viewheight, viewwidth, viewheight, r_fb.ghosttexcoord2f);
6528 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.ghosttexcoord2f);
6529 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6530 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6531 r_refdef.stats[r_stat_bloom_drawpixels] += viewwidth * viewheight;
6534 // updates old view angles for next pass
6535 VectorCopy(cl.viewangles, blur_oldangles);
6537 // copy view into the ghost texture
6538 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, viewx, viewy, viewwidth, viewheight);
6539 r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
6540 r_fb.ghosttexture_valid = true;
6543 if (r_fb.bloomwidth)
6545 // make the bloom texture
6546 R_Bloom_MakeTexture();
6549 #if _MSC_VER >= 1400
6550 #define sscanf sscanf_s
6552 memset(uservecs, 0, sizeof(uservecs));
6553 if (r_glsl_postprocess_uservec1_enable.integer)
6554 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6555 if (r_glsl_postprocess_uservec2_enable.integer)
6556 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6557 if (r_glsl_postprocess_uservec3_enable.integer)
6558 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6559 if (r_glsl_postprocess_uservec4_enable.integer)
6560 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6562 // render to the screen fbo
6563 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6564 GL_Color(1, 1, 1, 1);
6565 GL_BlendFunc(GL_ONE, GL_ZERO);
6567 viewtexture = r_fb.rt_screen->colortexture[0];
6568 bloomtexture = r_fb.rt_bloom ? r_fb.rt_bloom->colortexture[0] : NULL;
6570 if (r_rendertarget_debug.integer >= 0)
6572 r_rendertarget_t *rt = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, r_rendertarget_debug.integer);
6573 if (rt && rt->colortexture[0])
6575 viewtexture = rt->colortexture[0];
6576 bloomtexture = NULL;
6580 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.rt_screen->texcoord2f, bloomtexture ? r_fb.rt_bloom->texcoord2f : NULL);
6581 switch(vid.renderpath)
6583 case RENDERPATH_GL20:
6584 case RENDERPATH_GLES2:
6585 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6586 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , viewtexture);
6587 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , bloomtexture);
6588 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6589 if (r_glsl_permutation->loc_ViewTintColor >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6590 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6591 if (r_glsl_permutation->loc_UserVec1 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6592 if (r_glsl_permutation->loc_UserVec2 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6593 if (r_glsl_permutation->loc_UserVec3 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6594 if (r_glsl_permutation->loc_UserVec4 >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6595 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6596 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6597 if (r_glsl_permutation->loc_BloomColorSubtract >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6599 case RENDERPATH_D3D9:
6601 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6602 R_Mesh_TexBind(GL20TU_FIRST , viewtexture);
6603 R_Mesh_TexBind(GL20TU_SECOND , bloomtexture);
6604 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6605 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6606 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6607 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6608 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6609 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6610 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6611 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6612 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6613 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6616 case RENDERPATH_D3D10:
6617 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6619 case RENDERPATH_D3D11:
6620 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6622 case RENDERPATH_SOFT:
6623 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6624 R_Mesh_TexBind(GL20TU_FIRST , viewtexture);
6625 R_Mesh_TexBind(GL20TU_SECOND , bloomtexture);
6626 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6627 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6628 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6629 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6630 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6631 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6632 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6633 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6634 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6635 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6640 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6641 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6643 case RENDERPATH_GL11:
6644 case RENDERPATH_GL13:
6645 case RENDERPATH_GLES1:
6646 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6648 // apply a color tint to the whole view
6649 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6650 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6651 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6652 R_SetupShader_Generic_NoTexture(false, true);
6653 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6654 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6660 matrix4x4_t r_waterscrollmatrix;
6662 void R_UpdateFog(void)
6665 if (gamemode == GAME_NEHAHRA)
6667 if (gl_fogenable.integer)
6669 r_refdef.oldgl_fogenable = true;
6670 r_refdef.fog_density = gl_fogdensity.value;
6671 r_refdef.fog_red = gl_fogred.value;
6672 r_refdef.fog_green = gl_foggreen.value;
6673 r_refdef.fog_blue = gl_fogblue.value;
6674 r_refdef.fog_alpha = 1;
6675 r_refdef.fog_start = 0;
6676 r_refdef.fog_end = gl_skyclip.value;
6677 r_refdef.fog_height = 1<<30;
6678 r_refdef.fog_fadedepth = 128;
6680 else if (r_refdef.oldgl_fogenable)
6682 r_refdef.oldgl_fogenable = false;
6683 r_refdef.fog_density = 0;
6684 r_refdef.fog_red = 0;
6685 r_refdef.fog_green = 0;
6686 r_refdef.fog_blue = 0;
6687 r_refdef.fog_alpha = 0;
6688 r_refdef.fog_start = 0;
6689 r_refdef.fog_end = 0;
6690 r_refdef.fog_height = 1<<30;
6691 r_refdef.fog_fadedepth = 128;
6696 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6697 r_refdef.fog_start = max(0, r_refdef.fog_start);
6698 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6700 if (r_refdef.fog_density && r_drawfog.integer)
6702 r_refdef.fogenabled = true;
6703 // this is the point where the fog reaches 0.9986 alpha, which we
6704 // consider a good enough cutoff point for the texture
6705 // (0.9986 * 256 == 255.6)
6706 if (r_fog_exp2.integer)
6707 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6709 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6710 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6711 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6712 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6713 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6714 R_BuildFogHeightTexture();
6715 // fog color was already set
6716 // update the fog texture
6717 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)
6718 R_BuildFogTexture();
6719 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6720 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6723 r_refdef.fogenabled = false;
6726 if (r_refdef.fog_density)
6728 r_refdef.fogcolor[0] = r_refdef.fog_red;
6729 r_refdef.fogcolor[1] = r_refdef.fog_green;
6730 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6732 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6733 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6734 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6735 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6739 VectorCopy(r_refdef.fogcolor, fogvec);
6740 // color.rgb *= ContrastBoost * SceneBrightness;
6741 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6742 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6743 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6744 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6749 void R_UpdateVariables(void)
6753 r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6755 r_refdef.farclip = r_farclip_base.value;
6756 if (r_refdef.scene.worldmodel)
6757 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6758 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6760 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6761 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6762 r_refdef.polygonfactor = 0;
6763 r_refdef.polygonoffset = 0;
6764 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6765 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6767 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6768 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6769 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6770 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6771 r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6772 if (FAKELIGHT_ENABLED)
6774 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6776 else if (r_refdef.scene.worldmodel)
6778 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6780 if (r_showsurfaces.integer)
6782 r_refdef.scene.rtworld = false;
6783 r_refdef.scene.rtworldshadows = false;
6784 r_refdef.scene.rtdlight = false;
6785 r_refdef.scene.rtdlightshadows = false;
6786 r_refdef.scene.lightmapintensity = 0;
6789 r_gpuskeletal = false;
6790 switch(vid.renderpath)
6792 case RENDERPATH_GL20:
6793 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6794 case RENDERPATH_D3D9:
6795 case RENDERPATH_D3D10:
6796 case RENDERPATH_D3D11:
6797 case RENDERPATH_SOFT:
6798 case RENDERPATH_GLES2:
6799 if(!vid_gammatables_trivial)
6801 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6803 // build GLSL gamma texture
6804 #define RAMPWIDTH 256
6805 unsigned short ramp[RAMPWIDTH * 3];
6806 unsigned char rampbgr[RAMPWIDTH][4];
6809 r_texture_gammaramps_serial = vid_gammatables_serial;
6811 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6812 for(i = 0; i < RAMPWIDTH; ++i)
6814 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6815 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6816 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6819 if (r_texture_gammaramps)
6821 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6825 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6831 // remove GLSL gamma texture
6834 case RENDERPATH_GL11:
6835 case RENDERPATH_GL13:
6836 case RENDERPATH_GLES1:
6841 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6842 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6848 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6849 if( scenetype != r_currentscenetype ) {
6850 // store the old scenetype
6851 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6852 r_currentscenetype = scenetype;
6853 // move in the new scene
6854 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6863 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6865 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6866 if( scenetype == r_currentscenetype ) {
6867 return &r_refdef.scene;
6869 return &r_scenes_store[ scenetype ];
6873 static int R_SortEntities_Compare(const void *ap, const void *bp)
6875 const entity_render_t *a = *(const entity_render_t **)ap;
6876 const entity_render_t *b = *(const entity_render_t **)bp;
6879 if(a->model < b->model)
6881 if(a->model > b->model)
6885 // TODO possibly calculate the REAL skinnum here first using
6887 if(a->skinnum < b->skinnum)
6889 if(a->skinnum > b->skinnum)
6892 // everything we compared is equal
6895 static void R_SortEntities(void)
6897 // below or equal 2 ents, sorting never gains anything
6898 if(r_refdef.scene.numentities <= 2)
6901 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6909 int dpsoftrast_test;
6910 extern cvar_t r_shadow_bouncegrid;
6911 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
6913 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6915 rtexture_t *viewdepthtexture = NULL;
6916 rtexture_t *viewcolortexture = NULL;
6917 int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
6919 dpsoftrast_test = r_test.integer;
6921 if (r_timereport_active)
6922 R_TimeReport("start");
6923 r_textureframe++; // used only by R_GetCurrentTexture
6924 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
6926 if(R_CompileShader_CheckStaticParms())
6929 if (!r_drawentities.integer)
6930 r_refdef.scene.numentities = 0;
6931 else if (r_sortentities.integer)
6934 R_AnimCache_ClearCache();
6936 /* adjust for stereo display */
6937 if(R_Stereo_Active())
6939 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
6940 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6943 if (r_refdef.view.isoverlay)
6945 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6946 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6947 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6948 R_TimeReport("depthclear");
6950 r_refdef.view.showdebug = false;
6952 r_fb.water.enabled = false;
6953 r_fb.water.numwaterplanes = 0;
6955 R_RenderScene(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
6957 r_refdef.view.matrix = originalmatrix;
6963 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6965 r_refdef.view.matrix = originalmatrix;
6969 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6971 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6972 // in sRGB fallback, behave similar to true sRGB: convert this
6973 // value from linear to sRGB
6974 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6976 R_RenderView_UpdateViewVectors();
6978 R_Shadow_UpdateWorldLightSelection();
6980 // this will set up r_fb.rt_screen
6981 R_Bloom_StartFrame();
6983 // apply bloom brightness offset
6985 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
6987 // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
6990 viewfbo = r_fb.rt_screen->fbo;
6991 viewdepthtexture = r_fb.rt_screen->depthtexture;
6992 viewcolortexture = r_fb.rt_screen->colortexture[0];
6996 viewheight = height;
6999 R_Water_StartFrame();
7002 if (r_timereport_active)
7003 R_TimeReport("viewsetup");
7005 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7007 // clear the whole fbo every frame - otherwise the driver will consider
7008 // it to be an inter-frame texture and stall in multi-gpu configurations
7010 GL_ScissorTest(false);
7011 R_ClearScreen(r_refdef.fogenabled);
7012 if (r_timereport_active)
7013 R_TimeReport("viewclear");
7015 r_refdef.view.clear = true;
7017 r_refdef.view.showdebug = true;
7020 if (r_timereport_active)
7021 R_TimeReport("visibility");
7023 R_AnimCache_CacheVisibleEntities();
7024 if (r_timereport_active)
7025 R_TimeReport("animcache");
7027 R_Shadow_UpdateBounceGridTexture();
7028 if (r_timereport_active && r_shadow_bouncegrid.integer)
7029 R_TimeReport("bouncegrid");
7031 r_fb.water.numwaterplanes = 0;
7032 if (r_fb.water.enabled)
7033 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7035 // for the actual view render we use scissoring a fair amount, so scissor
7036 // test needs to be on
7038 GL_ScissorTest(true);
7039 GL_Scissor(viewx, viewy, viewwidth, viewheight);
7040 R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7041 r_fb.water.numwaterplanes = 0;
7043 // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
7044 GL_ScissorTest(false);
7046 R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
7047 if (r_timereport_active)
7048 R_TimeReport("blendview");
7050 r_refdef.view.matrix = originalmatrix;
7055 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7057 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7059 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7060 if (r_timereport_active)
7061 R_TimeReport("waterworld");
7064 // don't let sound skip if going slow
7065 if (r_refdef.scene.extraupdate)
7068 R_DrawModelsAddWaterPlanes();
7069 if (r_timereport_active)
7070 R_TimeReport("watermodels");
7072 if (r_fb.water.numwaterplanes)
7074 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7075 if (r_timereport_active)
7076 R_TimeReport("waterscenes");
7080 extern cvar_t cl_locs_show;
7081 static void R_DrawLocs(void);
7082 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7083 static void R_DrawModelDecals(void);
7084 extern cvar_t cl_decals_newsystem;
7085 extern qboolean r_shadow_usingdeferredprepass;
7086 extern int r_shadow_shadowmapatlas_modelshadows_size;
7087 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7089 qboolean shadowmapping = false;
7091 if (r_timereport_active)
7092 R_TimeReport("beginscene");
7094 r_refdef.stats[r_stat_renders]++;
7098 // don't let sound skip if going slow
7099 if (r_refdef.scene.extraupdate)
7102 R_MeshQueue_BeginScene();
7106 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);
7108 if (r_timereport_active)
7109 R_TimeReport("skystartframe");
7111 if (cl.csqc_vidvars.drawworld)
7113 // don't let sound skip if going slow
7114 if (r_refdef.scene.extraupdate)
7117 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7119 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7120 if (r_timereport_active)
7121 R_TimeReport("worldsky");
7124 if (R_DrawBrushModelsSky() && r_timereport_active)
7125 R_TimeReport("bmodelsky");
7127 if (skyrendermasked && skyrenderlater)
7129 // we have to force off the water clipping plane while rendering sky
7130 R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7132 R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7133 if (r_timereport_active)
7134 R_TimeReport("sky");
7138 // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
7139 r_shadow_viewfbo = viewfbo;
7140 r_shadow_viewdepthtexture = viewdepthtexture;
7141 r_shadow_viewcolortexture = viewcolortexture;
7142 r_shadow_viewx = viewx;
7143 r_shadow_viewy = viewy;
7144 r_shadow_viewwidth = viewwidth;
7145 r_shadow_viewheight = viewheight;
7147 R_Shadow_PrepareModelShadows();
7148 R_Shadow_PrepareLights();
7149 if (r_timereport_active)
7150 R_TimeReport("preparelights");
7152 // render all the shadowmaps that will be used for this view
7153 shadowmapping = R_Shadow_ShadowMappingEnabled();
7154 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7156 R_Shadow_DrawShadowMaps();
7157 if (r_timereport_active)
7158 R_TimeReport("shadowmaps");
7161 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7162 if (r_shadow_usingdeferredprepass)
7163 R_Shadow_DrawPrepass();
7165 // now we begin the forward pass of the view render
7166 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7168 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7169 if (r_timereport_active)
7170 R_TimeReport("worlddepth");
7172 if (r_depthfirst.integer >= 2)
7174 R_DrawModelsDepth();
7175 if (r_timereport_active)
7176 R_TimeReport("modeldepth");
7179 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7181 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7182 if (r_timereport_active)
7183 R_TimeReport("world");
7186 // don't let sound skip if going slow
7187 if (r_refdef.scene.extraupdate)
7191 if (r_timereport_active)
7192 R_TimeReport("models");
7194 // don't let sound skip if going slow
7195 if (r_refdef.scene.extraupdate)
7198 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7200 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7201 R_Shadow_DrawModelShadows();
7202 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7203 // don't let sound skip if going slow
7204 if (r_refdef.scene.extraupdate)
7208 if (!r_shadow_usingdeferredprepass)
7210 R_Shadow_DrawLights();
7211 if (r_timereport_active)
7212 R_TimeReport("rtlights");
7215 // don't let sound skip if going slow
7216 if (r_refdef.scene.extraupdate)
7219 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7221 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7222 R_Shadow_DrawModelShadows();
7223 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7224 // don't let sound skip if going slow
7225 if (r_refdef.scene.extraupdate)
7229 if (cl.csqc_vidvars.drawworld)
7231 if (cl_decals_newsystem.integer)
7233 R_DrawModelDecals();
7234 if (r_timereport_active)
7235 R_TimeReport("modeldecals");
7240 if (r_timereport_active)
7241 R_TimeReport("decals");
7245 if (r_timereport_active)
7246 R_TimeReport("particles");
7249 if (r_timereport_active)
7250 R_TimeReport("explosions");
7253 if (r_refdef.view.showdebug)
7255 if (cl_locs_show.integer)
7258 if (r_timereport_active)
7259 R_TimeReport("showlocs");
7262 if (r_drawportals.integer)
7265 if (r_timereport_active)
7266 R_TimeReport("portals");
7269 if (r_showbboxes_client.value > 0)
7271 R_DrawEntityBBoxes(CLVM_prog);
7272 if (r_timereport_active)
7273 R_TimeReport("clbboxes");
7275 if (r_showbboxes.value > 0)
7277 R_DrawEntityBBoxes(SVVM_prog);
7278 if (r_timereport_active)
7279 R_TimeReport("svbboxes");
7283 if (r_transparent.integer)
7285 R_MeshQueue_RenderTransparent();
7286 if (r_timereport_active)
7287 R_TimeReport("drawtrans");
7290 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 || r_showoverdraw.value > 0))
7292 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7293 if (r_timereport_active)
7294 R_TimeReport("worlddebug");
7295 R_DrawModelsDebug();
7296 if (r_timereport_active)
7297 R_TimeReport("modeldebug");
7300 if (cl.csqc_vidvars.drawworld)
7302 R_Shadow_DrawCoronas();
7303 if (r_timereport_active)
7304 R_TimeReport("coronas");
7309 GL_DepthTest(false);
7310 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7311 GL_Color(1, 1, 1, 1);
7312 qglBegin(GL_POLYGON);
7313 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7314 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7315 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7316 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7318 qglBegin(GL_POLYGON);
7319 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
7320 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
7321 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
7322 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
7324 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7328 // don't let sound skip if going slow
7329 if (r_refdef.scene.extraupdate)
7333 static const unsigned short bboxelements[36] =
7343 #define BBOXEDGES 13
7344 static const float bboxedges[BBOXEDGES][6] =
7347 { 0, 0, 0, 1, 1, 1 },
7349 { 0, 0, 0, 0, 1, 0 },
7350 { 0, 0, 0, 1, 0, 0 },
7351 { 0, 1, 0, 1, 1, 0 },
7352 { 1, 0, 0, 1, 1, 0 },
7354 { 0, 0, 1, 0, 1, 1 },
7355 { 0, 0, 1, 1, 0, 1 },
7356 { 0, 1, 1, 1, 1, 1 },
7357 { 1, 0, 1, 1, 1, 1 },
7359 { 0, 0, 0, 0, 0, 1 },
7360 { 1, 0, 0, 1, 0, 1 },
7361 { 0, 1, 0, 0, 1, 1 },
7362 { 1, 1, 0, 1, 1, 1 },
7365 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7367 int numvertices = BBOXEDGES * 8;
7368 float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7369 int numtriangles = BBOXEDGES * 12;
7370 unsigned short elements[BBOXEDGES * 36];
7372 float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7374 RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7376 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7377 GL_DepthMask(false);
7378 GL_DepthRange(0, 1);
7379 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7381 for (edge = 0; edge < BBOXEDGES; edge++)
7383 for (i = 0; i < 3; i++)
7385 edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7386 edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7388 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7389 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7390 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7391 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7392 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7393 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7394 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7395 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7396 for (i = 0; i < 36; i++)
7397 elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7399 R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7400 if (r_refdef.fogenabled)
7402 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7404 f1 = RSurf_FogVertex(v);
7406 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7407 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7408 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7411 R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7412 R_Mesh_ResetTextureState();
7413 R_SetupShader_Generic_NoTexture(false, false);
7414 R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7417 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7419 // hacky overloading of the parameters
7420 prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7423 prvm_edict_t *edict;
7425 GL_CullFace(GL_NONE);
7426 R_SetupShader_Generic_NoTexture(false, false);
7428 for (i = 0;i < numsurfaces;i++)
7430 edict = PRVM_EDICT_NUM(surfacelist[i]);
7431 switch ((int)PRVM_serveredictfloat(edict, solid))
7433 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7434 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7435 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7436 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7437 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7438 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7439 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7441 if (prog == CLVM_prog)
7442 color[3] *= r_showbboxes_client.value;
7444 color[3] *= r_showbboxes.value;
7445 color[3] = bound(0, color[3], 1);
7446 GL_DepthTest(!r_showdisabledepthtest.integer);
7447 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7451 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7454 prvm_edict_t *edict;
7460 for (i = 0; i < prog->num_edicts; i++)
7462 edict = PRVM_EDICT_NUM(i);
7463 if (edict->priv.server->free)
7465 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7466 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7468 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7470 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7471 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7475 static const int nomodelelement3i[24] =
7487 static const unsigned short nomodelelement3s[24] =
7499 static const float nomodelvertex3f[6*3] =
7509 static const float nomodelcolor4f[6*4] =
7511 0.0f, 0.0f, 0.5f, 1.0f,
7512 0.0f, 0.0f, 0.5f, 1.0f,
7513 0.0f, 0.5f, 0.0f, 1.0f,
7514 0.0f, 0.5f, 0.0f, 1.0f,
7515 0.5f, 0.0f, 0.0f, 1.0f,
7516 0.5f, 0.0f, 0.0f, 1.0f
7519 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7525 RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7527 // this is only called once per entity so numsurfaces is always 1, and
7528 // surfacelist is always {0}, so this code does not handle batches
7530 if (rsurface.ent_flags & RENDER_ADDITIVE)
7532 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7533 GL_DepthMask(false);
7535 else if (ent->alpha < 1)
7537 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7538 GL_DepthMask(false);
7542 GL_BlendFunc(GL_ONE, GL_ZERO);
7545 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7546 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7547 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7548 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7549 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7550 for (i = 0, c = color4f;i < 6;i++, c += 4)
7552 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7553 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7554 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7557 if (r_refdef.fogenabled)
7559 for (i = 0, c = color4f;i < 6;i++, c += 4)
7561 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7563 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7564 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7565 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7568 // R_Mesh_ResetTextureState();
7569 R_SetupShader_Generic_NoTexture(false, false);
7570 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7571 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7574 void R_DrawNoModel(entity_render_t *ent)
7577 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7578 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7579 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7581 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7584 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7586 vec3_t right1, right2, diff, normal;
7588 VectorSubtract (org2, org1, normal);
7590 // calculate 'right' vector for start
7591 VectorSubtract (r_refdef.view.origin, org1, diff);
7592 CrossProduct (normal, diff, right1);
7593 VectorNormalize (right1);
7595 // calculate 'right' vector for end
7596 VectorSubtract (r_refdef.view.origin, org2, diff);
7597 CrossProduct (normal, diff, right2);
7598 VectorNormalize (right2);
7600 vert[ 0] = org1[0] + width * right1[0];
7601 vert[ 1] = org1[1] + width * right1[1];
7602 vert[ 2] = org1[2] + width * right1[2];
7603 vert[ 3] = org1[0] - width * right1[0];
7604 vert[ 4] = org1[1] - width * right1[1];
7605 vert[ 5] = org1[2] - width * right1[2];
7606 vert[ 6] = org2[0] - width * right2[0];
7607 vert[ 7] = org2[1] - width * right2[1];
7608 vert[ 8] = org2[2] - width * right2[2];
7609 vert[ 9] = org2[0] + width * right2[0];
7610 vert[10] = org2[1] + width * right2[1];
7611 vert[11] = org2[2] + width * right2[2];
7614 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7616 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7617 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7618 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7619 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7620 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7621 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7622 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7623 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7624 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7625 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7626 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7627 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7630 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7635 VectorSet(v, x, y, z);
7636 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7637 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7639 if (i == mesh->numvertices)
7641 if (mesh->numvertices < mesh->maxvertices)
7643 VectorCopy(v, vertex3f);
7644 mesh->numvertices++;
7646 return mesh->numvertices;
7652 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7656 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7657 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7658 e = mesh->element3i + mesh->numtriangles * 3;
7659 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7661 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7662 if (mesh->numtriangles < mesh->maxtriangles)
7667 mesh->numtriangles++;
7669 element[1] = element[2];
7673 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7677 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7678 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7679 e = mesh->element3i + mesh->numtriangles * 3;
7680 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7682 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7683 if (mesh->numtriangles < mesh->maxtriangles)
7688 mesh->numtriangles++;
7690 element[1] = element[2];
7694 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7695 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7697 int planenum, planenum2;
7700 mplane_t *plane, *plane2;
7702 double temppoints[2][256*3];
7703 // figure out how large a bounding box we need to properly compute this brush
7705 for (w = 0;w < numplanes;w++)
7706 maxdist = max(maxdist, fabs(planes[w].dist));
7707 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7708 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7709 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7713 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7714 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7716 if (planenum2 == planenum)
7718 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);
7721 if (tempnumpoints < 3)
7723 // generate elements forming a triangle fan for this polygon
7724 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7728 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)
7730 texturelayer_t *layer;
7731 layer = t->currentlayers + t->currentnumlayers++;
7733 layer->depthmask = depthmask;
7734 layer->blendfunc1 = blendfunc1;
7735 layer->blendfunc2 = blendfunc2;
7736 layer->texture = texture;
7737 layer->texmatrix = *matrix;
7738 layer->color[0] = r;
7739 layer->color[1] = g;
7740 layer->color[2] = b;
7741 layer->color[3] = a;
7744 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7746 if(parms[0] == 0 && parms[1] == 0)
7748 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7749 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7754 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7757 index = parms[2] + rsurface.shadertime * parms[3];
7758 index -= floor(index);
7759 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7762 case Q3WAVEFUNC_NONE:
7763 case Q3WAVEFUNC_NOISE:
7764 case Q3WAVEFUNC_COUNT:
7767 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7768 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7769 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7770 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7771 case Q3WAVEFUNC_TRIANGLE:
7773 f = index - floor(index);
7786 f = parms[0] + parms[1] * f;
7787 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7788 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7792 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7799 matrix4x4_t matrix, temp;
7800 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7801 // it's better to have one huge fixup every 9 hours than gradual
7802 // degradation over time which looks consistently bad after many hours.
7804 // tcmod scroll in particular suffers from this degradation which can't be
7805 // effectively worked around even with floor() tricks because we don't
7806 // know if tcmod scroll is the last tcmod being applied, and for clampmap
7807 // a workaround involving floor() would be incorrect anyway...
7808 shadertime = rsurface.shadertime;
7809 if (shadertime >= 32768.0f)
7810 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7811 switch(tcmod->tcmod)
7815 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7816 matrix = r_waterscrollmatrix;
7818 matrix = identitymatrix;
7820 case Q3TCMOD_ENTITYTRANSLATE:
7821 // this is used in Q3 to allow the gamecode to control texcoord
7822 // scrolling on the entity, which is not supported in darkplaces yet.
7823 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7825 case Q3TCMOD_ROTATE:
7826 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7827 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7828 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7831 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7833 case Q3TCMOD_SCROLL:
7834 // this particular tcmod is a "bug for bug" compatible one with regards to
7835 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7836 // specifically did the wrapping and so we must mimic that...
7837 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7838 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7839 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7841 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7842 w = (int) tcmod->parms[0];
7843 h = (int) tcmod->parms[1];
7844 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7846 idx = (int) floor(f * w * h);
7847 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7849 case Q3TCMOD_STRETCH:
7850 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7851 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7853 case Q3TCMOD_TRANSFORM:
7854 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7855 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7856 VectorSet(tcmat + 6, 0 , 0 , 1);
7857 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7858 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7860 case Q3TCMOD_TURBULENT:
7861 // this is handled in the RSurf_PrepareVertices function
7862 matrix = identitymatrix;
7866 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7869 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7871 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7872 char name[MAX_QPATH];
7873 skinframe_t *skinframe;
7874 unsigned char pixels[296*194];
7875 strlcpy(cache->name, skinname, sizeof(cache->name));
7876 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7877 if (developer_loading.integer)
7878 Con_Printf("loading %s\n", name);
7879 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7880 if (!skinframe || !skinframe->base)
7883 fs_offset_t filesize;
7885 f = FS_LoadFile(name, tempmempool, true, &filesize);
7888 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7889 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7893 cache->skinframe = skinframe;
7896 texture_t *R_GetCurrentTexture(texture_t *t)
7899 const entity_render_t *ent = rsurface.entity;
7900 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7901 q3shaderinfo_layer_tcmod_t *tcmod;
7902 float specularscale = 0.0f;
7904 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7905 return t->currentframe;
7906 t->update_lastrenderframe = r_textureframe;
7907 t->update_lastrenderentity = (void *)ent;
7909 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7910 t->camera_entity = ent->entitynumber;
7912 t->camera_entity = 0;
7914 // switch to an alternate material if this is a q1bsp animated material
7916 texture_t *texture = t;
7917 int s = rsurface.ent_skinnum;
7918 if ((unsigned int)s >= (unsigned int)model->numskins)
7920 if (model->skinscenes)
7922 if (model->skinscenes[s].framecount > 1)
7923 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7925 s = model->skinscenes[s].firstframe;
7928 t = t + s * model->num_surfaces;
7931 // use an alternate animation if the entity's frame is not 0,
7932 // and only if the texture has an alternate animation
7933 if (t->animated == 2) // q2bsp
7934 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
7935 else if (rsurface.ent_alttextures && t->anim_total[1])
7936 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7938 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7940 texture->currentframe = t;
7943 // update currentskinframe to be a qw skin or animation frame
7944 if (rsurface.ent_qwskin >= 0)
7946 i = rsurface.ent_qwskin;
7947 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7949 r_qwskincache_size = cl.maxclients;
7951 Mem_Free(r_qwskincache);
7952 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7954 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7955 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7956 t->currentskinframe = r_qwskincache[i].skinframe;
7957 if (t->materialshaderpass && t->currentskinframe == NULL)
7958 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7960 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
7961 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7962 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
7963 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
7965 t->currentmaterialflags = t->basematerialflags;
7966 t->currentalpha = rsurface.entity->alpha * t->basealpha;
7967 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7968 t->currentalpha *= r_wateralpha.value;
7969 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7970 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7971 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7972 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7974 // decide on which type of lighting to use for this surface
7975 if (rsurface.entity->render_modellight_forced)
7976 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7977 if (rsurface.entity->render_rtlight_disabled)
7978 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
7979 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
7981 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
7982 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
7983 for (q = 0; q < 3; q++)
7985 t->render_glowmod[q] = rsurface.entity->glowmod[q];
7986 t->render_modellight_lightdir[q] = q == 2;
7987 t->render_modellight_ambient[q] = 1;
7988 t->render_modellight_diffuse[q] = 0;
7989 t->render_modellight_specular[q] = 0;
7990 t->render_lightmap_ambient[q] = 0;
7991 t->render_lightmap_diffuse[q] = 0;
7992 t->render_lightmap_specular[q] = 0;
7993 t->render_rtlight_diffuse[q] = 0;
7994 t->render_rtlight_specular[q] = 0;
7997 else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
7999 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8000 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8001 for (q = 0; q < 3; q++)
8003 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8004 t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8005 t->render_modellight_lightdir[q] = q == 2;
8006 t->render_modellight_diffuse[q] = 0;
8007 t->render_modellight_specular[q] = 0;
8008 t->render_lightmap_ambient[q] = 0;
8009 t->render_lightmap_diffuse[q] = 0;
8010 t->render_lightmap_specular[q] = 0;
8011 t->render_rtlight_diffuse[q] = 0;
8012 t->render_rtlight_specular[q] = 0;
8015 else if (FAKELIGHT_ENABLED)
8017 // no modellight if using fakelight for the map
8018 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8019 for (q = 0; q < 3; q++)
8021 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8022 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8023 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8024 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8025 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8026 t->render_lightmap_ambient[q] = 0;
8027 t->render_lightmap_diffuse[q] = 0;
8028 t->render_lightmap_specular[q] = 0;
8029 t->render_rtlight_diffuse[q] = 0;
8030 t->render_rtlight_specular[q] = 0;
8033 else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8035 // ambient + single direction light (modellight)
8036 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8037 for (q = 0; q < 3; q++)
8039 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8040 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8041 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8042 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8043 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8044 t->render_lightmap_ambient[q] = 0;
8045 t->render_lightmap_diffuse[q] = 0;
8046 t->render_lightmap_specular[q] = 0;
8047 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8048 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8053 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8054 for (q = 0; q < 3; q++)
8056 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8057 t->render_modellight_lightdir[q] = q == 2;
8058 t->render_modellight_ambient[q] = 0;
8059 t->render_modellight_diffuse[q] = 0;
8060 t->render_modellight_specular[q] = 0;
8061 t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8062 t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8063 t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8064 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8065 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8069 if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
8071 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
8072 // attribute, we punt it to the lightmap path and hope for the best,
8073 // but lighting doesn't work.
8075 // FIXME: this is fine for effects but CSQC polygons should be subject
8077 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
8078 for (q = 0; q < 3; q++)
8080 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8081 t->render_modellight_lightdir[q] = q == 2;
8082 t->render_modellight_ambient[q] = 0;
8083 t->render_modellight_diffuse[q] = 0;
8084 t->render_modellight_specular[q] = 0;
8085 t->render_lightmap_ambient[q] = 0;
8086 t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8087 t->render_lightmap_specular[q] = 0;
8088 t->render_rtlight_diffuse[q] = 0;
8089 t->render_rtlight_specular[q] = 0;
8093 for (q = 0; q < 3; q++)
8095 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8096 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8099 if (rsurface.ent_flags & RENDER_ADDITIVE)
8100 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8101 else if (t->currentalpha < 1)
8102 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8103 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8104 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8105 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8106 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8107 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8108 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8109 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8110 if (t->backgroundshaderpass)
8111 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8112 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8114 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8115 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8118 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8119 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8121 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8122 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8124 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8125 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8127 // there is no tcmod
8128 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8130 t->currenttexmatrix = r_waterscrollmatrix;
8131 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8133 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8135 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8136 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8139 if (t->materialshaderpass)
8140 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8141 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8143 t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8144 if (t->currentskinframe->qpixels)
8145 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8146 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8147 if (!t->basetexture)
8148 t->basetexture = r_texture_notexture;
8149 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8150 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8151 t->nmaptexture = t->currentskinframe->nmap;
8152 if (!t->nmaptexture)
8153 t->nmaptexture = r_texture_blanknormalmap;
8154 t->glosstexture = r_texture_black;
8155 t->glowtexture = t->currentskinframe->glow;
8156 t->fogtexture = t->currentskinframe->fog;
8157 t->reflectmasktexture = t->currentskinframe->reflect;
8158 if (t->backgroundshaderpass)
8160 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8161 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8162 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8163 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8164 t->backgroundglosstexture = r_texture_black;
8165 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8166 if (!t->backgroundnmaptexture)
8167 t->backgroundnmaptexture = r_texture_blanknormalmap;
8168 // make sure that if glow is going to be used, both textures are not NULL
8169 if (!t->backgroundglowtexture && t->glowtexture)
8170 t->backgroundglowtexture = r_texture_black;
8171 if (!t->glowtexture && t->backgroundglowtexture)
8172 t->glowtexture = r_texture_black;
8176 t->backgroundbasetexture = r_texture_white;
8177 t->backgroundnmaptexture = r_texture_blanknormalmap;
8178 t->backgroundglosstexture = r_texture_black;
8179 t->backgroundglowtexture = NULL;
8181 t->specularpower = r_shadow_glossexponent.value;
8182 // TODO: store reference values for these in the texture?
8183 if (r_shadow_gloss.integer > 0)
8185 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8187 if (r_shadow_glossintensity.value > 0)
8189 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8190 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8191 specularscale = r_shadow_glossintensity.value;
8194 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8196 t->glosstexture = r_texture_white;
8197 t->backgroundglosstexture = r_texture_white;
8198 specularscale = r_shadow_gloss2intensity.value;
8199 t->specularpower = r_shadow_gloss2exponent.value;
8202 specularscale *= t->specularscalemod;
8203 t->specularpower *= t->specularpowermod;
8205 // lightmaps mode looks bad with dlights using actual texturing, so turn
8206 // off the colormap and glossmap, but leave the normalmap on as it still
8207 // accurately represents the shading involved
8208 if (gl_lightmaps.integer)
8210 t->basetexture = r_texture_grey128;
8211 t->pantstexture = r_texture_black;
8212 t->shirttexture = r_texture_black;
8213 if (gl_lightmaps.integer < 2)
8214 t->nmaptexture = r_texture_blanknormalmap;
8215 t->glosstexture = r_texture_black;
8216 t->glowtexture = NULL;
8217 t->fogtexture = NULL;
8218 t->reflectmasktexture = NULL;
8219 t->backgroundbasetexture = NULL;
8220 if (gl_lightmaps.integer < 2)
8221 t->backgroundnmaptexture = r_texture_blanknormalmap;
8222 t->backgroundglosstexture = r_texture_black;
8223 t->backgroundglowtexture = NULL;
8225 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8228 if (specularscale != 1.0f)
8230 for (q = 0; q < 3; q++)
8232 t->render_modellight_specular[q] *= specularscale;
8233 t->render_lightmap_specular[q] *= specularscale;
8234 t->render_rtlight_specular[q] *= specularscale;
8238 t->currentnumlayers = 0;
8239 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8241 int blendfunc1, blendfunc2;
8243 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8245 blendfunc1 = GL_SRC_ALPHA;
8246 blendfunc2 = GL_ONE;
8248 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8250 blendfunc1 = GL_SRC_ALPHA;
8251 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8253 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8255 blendfunc1 = t->customblendfunc[0];
8256 blendfunc2 = t->customblendfunc[1];
8260 blendfunc1 = GL_ONE;
8261 blendfunc2 = GL_ZERO;
8263 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8264 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8266 // basic lit geometry
8267 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8268 // add pants/shirt if needed
8269 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8270 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8271 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8272 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8276 // basic lit geometry
8277 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8278 // add pants/shirt if needed
8279 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8280 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8281 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8282 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8283 // now add ambient passes if needed
8284 if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8286 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
8287 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8288 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
8289 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8290 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
8293 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8294 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
8295 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8297 // if this is opaque use alpha blend which will darken the earlier
8300 // if this is an alpha blended material, all the earlier passes
8301 // were darkened by fog already, so we only need to add the fog
8302 // color ontop through the fog mask texture
8304 // if this is an additive blended material, all the earlier passes
8305 // were darkened by fog already, and we should not add fog color
8306 // (because the background was not darkened, there is no fog color
8307 // that was lost behind it).
8308 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
8315 rsurfacestate_t rsurface;
8317 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8319 dp_model_t *model = ent->model;
8320 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8322 rsurface.entity = (entity_render_t *)ent;
8323 rsurface.skeleton = ent->skeleton;
8324 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8325 rsurface.ent_skinnum = ent->skinnum;
8326 rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
8327 rsurface.ent_flags = ent->flags;
8328 if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8329 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8330 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8331 rsurface.matrix = ent->matrix;
8332 rsurface.inversematrix = ent->inversematrix;
8333 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8334 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8335 R_EntityMatrix(&rsurface.matrix);
8336 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8337 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8338 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8339 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8340 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8341 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8342 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8343 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8344 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8345 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8346 if (ent->model->brush.submodel && !prepass)
8348 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8349 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8351 // if the animcache code decided it should use the shader path, skip the deform step
8352 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8353 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8354 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8355 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8356 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8357 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8359 if (ent->animcache_vertex3f)
8361 r_refdef.stats[r_stat_batch_entitycache_count]++;
8362 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8363 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8364 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8365 rsurface.modelvertex3f = ent->animcache_vertex3f;
8366 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8367 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8368 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8369 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8370 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8371 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8372 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8373 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8374 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8375 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8376 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8377 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8378 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8379 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8381 else if (wanttangents)
8383 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8384 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8385 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8386 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8387 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8388 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8389 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8390 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8391 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8392 rsurface.modelvertexmesh = NULL;
8393 rsurface.modelvertexmesh_vertexbuffer = NULL;
8394 rsurface.modelvertexmesh_bufferoffset = 0;
8395 rsurface.modelvertex3f_vertexbuffer = NULL;
8396 rsurface.modelvertex3f_bufferoffset = 0;
8397 rsurface.modelvertex3f_vertexbuffer = 0;
8398 rsurface.modelvertex3f_bufferoffset = 0;
8399 rsurface.modelsvector3f_vertexbuffer = 0;
8400 rsurface.modelsvector3f_bufferoffset = 0;
8401 rsurface.modeltvector3f_vertexbuffer = 0;
8402 rsurface.modeltvector3f_bufferoffset = 0;
8403 rsurface.modelnormal3f_vertexbuffer = 0;
8404 rsurface.modelnormal3f_bufferoffset = 0;
8406 else if (wantnormals)
8408 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8409 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8410 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8411 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8412 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8413 rsurface.modelsvector3f = NULL;
8414 rsurface.modeltvector3f = NULL;
8415 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8416 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8417 rsurface.modelvertexmesh = NULL;
8418 rsurface.modelvertexmesh_vertexbuffer = NULL;
8419 rsurface.modelvertexmesh_bufferoffset = 0;
8420 rsurface.modelvertex3f_vertexbuffer = NULL;
8421 rsurface.modelvertex3f_bufferoffset = 0;
8422 rsurface.modelvertex3f_vertexbuffer = 0;
8423 rsurface.modelvertex3f_bufferoffset = 0;
8424 rsurface.modelsvector3f_vertexbuffer = 0;
8425 rsurface.modelsvector3f_bufferoffset = 0;
8426 rsurface.modeltvector3f_vertexbuffer = 0;
8427 rsurface.modeltvector3f_bufferoffset = 0;
8428 rsurface.modelnormal3f_vertexbuffer = 0;
8429 rsurface.modelnormal3f_bufferoffset = 0;
8433 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8434 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8435 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8436 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8437 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8438 rsurface.modelsvector3f = NULL;
8439 rsurface.modeltvector3f = NULL;
8440 rsurface.modelnormal3f = NULL;
8441 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8442 rsurface.modelvertexmesh = NULL;
8443 rsurface.modelvertexmesh_vertexbuffer = NULL;
8444 rsurface.modelvertexmesh_bufferoffset = 0;
8445 rsurface.modelvertex3f_vertexbuffer = NULL;
8446 rsurface.modelvertex3f_bufferoffset = 0;
8447 rsurface.modelvertex3f_vertexbuffer = 0;
8448 rsurface.modelvertex3f_bufferoffset = 0;
8449 rsurface.modelsvector3f_vertexbuffer = 0;
8450 rsurface.modelsvector3f_bufferoffset = 0;
8451 rsurface.modeltvector3f_vertexbuffer = 0;
8452 rsurface.modeltvector3f_bufferoffset = 0;
8453 rsurface.modelnormal3f_vertexbuffer = 0;
8454 rsurface.modelnormal3f_bufferoffset = 0;
8456 rsurface.modelgeneratedvertex = true;
8460 if (rsurface.entityskeletaltransform3x4)
8462 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8463 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8464 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8465 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8469 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8470 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8471 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8472 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8474 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8475 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8476 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8477 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8478 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8479 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8480 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8481 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8482 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8483 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8484 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8485 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8486 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8487 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8488 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8489 rsurface.modelgeneratedvertex = false;
8491 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8492 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8493 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8494 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8495 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8496 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8497 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8498 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8499 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8500 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8501 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8502 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8503 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8504 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8505 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8506 rsurface.modelelement3i = model->surfmesh.data_element3i;
8507 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8508 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8509 rsurface.modelelement3s = model->surfmesh.data_element3s;
8510 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8511 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8512 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8513 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8514 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8515 rsurface.modelsurfaces = model->data_surfaces;
8516 rsurface.batchgeneratedvertex = false;
8517 rsurface.batchfirstvertex = 0;
8518 rsurface.batchnumvertices = 0;
8519 rsurface.batchfirsttriangle = 0;
8520 rsurface.batchnumtriangles = 0;
8521 rsurface.batchvertex3f = NULL;
8522 rsurface.batchvertex3f_vertexbuffer = NULL;
8523 rsurface.batchvertex3f_bufferoffset = 0;
8524 rsurface.batchsvector3f = NULL;
8525 rsurface.batchsvector3f_vertexbuffer = NULL;
8526 rsurface.batchsvector3f_bufferoffset = 0;
8527 rsurface.batchtvector3f = NULL;
8528 rsurface.batchtvector3f_vertexbuffer = NULL;
8529 rsurface.batchtvector3f_bufferoffset = 0;
8530 rsurface.batchnormal3f = NULL;
8531 rsurface.batchnormal3f_vertexbuffer = NULL;
8532 rsurface.batchnormal3f_bufferoffset = 0;
8533 rsurface.batchlightmapcolor4f = NULL;
8534 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8535 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8536 rsurface.batchtexcoordtexture2f = NULL;
8537 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8538 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8539 rsurface.batchtexcoordlightmap2f = NULL;
8540 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8541 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8542 rsurface.batchskeletalindex4ub = NULL;
8543 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8544 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8545 rsurface.batchskeletalweight4ub = NULL;
8546 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8547 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8548 rsurface.batchvertexmesh = NULL;
8549 rsurface.batchvertexmesh_vertexbuffer = NULL;
8550 rsurface.batchvertexmesh_bufferoffset = 0;
8551 rsurface.batchelement3i = NULL;
8552 rsurface.batchelement3i_indexbuffer = NULL;
8553 rsurface.batchelement3i_bufferoffset = 0;
8554 rsurface.batchelement3s = NULL;
8555 rsurface.batchelement3s_indexbuffer = NULL;
8556 rsurface.batchelement3s_bufferoffset = 0;
8557 rsurface.passcolor4f = NULL;
8558 rsurface.passcolor4f_vertexbuffer = NULL;
8559 rsurface.passcolor4f_bufferoffset = 0;
8560 rsurface.forcecurrenttextureupdate = false;
8563 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
8565 rsurface.entity = r_refdef.scene.worldentity;
8566 rsurface.skeleton = NULL;
8567 rsurface.ent_skinnum = 0;
8568 rsurface.ent_qwskin = -1;
8569 rsurface.ent_flags = entflags;
8570 rsurface.shadertime = r_refdef.scene.time - shadertime;
8571 rsurface.modelnumvertices = numvertices;
8572 rsurface.modelnumtriangles = numtriangles;
8573 rsurface.matrix = *matrix;
8574 rsurface.inversematrix = *inversematrix;
8575 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8576 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8577 R_EntityMatrix(&rsurface.matrix);
8578 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8579 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8580 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8581 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8582 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8583 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8584 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8585 rsurface.frameblend[0].lerp = 1;
8586 rsurface.ent_alttextures = false;
8587 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8588 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8589 rsurface.entityskeletaltransform3x4 = NULL;
8590 rsurface.entityskeletaltransform3x4buffer = NULL;
8591 rsurface.entityskeletaltransform3x4offset = 0;
8592 rsurface.entityskeletaltransform3x4size = 0;
8593 rsurface.entityskeletalnumtransforms = 0;
8594 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8595 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8596 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8597 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8600 rsurface.modelvertex3f = (float *)vertex3f;
8601 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8602 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8603 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8605 else if (wantnormals)
8607 rsurface.modelvertex3f = (float *)vertex3f;
8608 rsurface.modelsvector3f = NULL;
8609 rsurface.modeltvector3f = NULL;
8610 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8614 rsurface.modelvertex3f = (float *)vertex3f;
8615 rsurface.modelsvector3f = NULL;
8616 rsurface.modeltvector3f = NULL;
8617 rsurface.modelnormal3f = NULL;
8619 rsurface.modelvertexmesh = NULL;
8620 rsurface.modelvertexmesh_vertexbuffer = NULL;
8621 rsurface.modelvertexmesh_bufferoffset = 0;
8622 rsurface.modelvertex3f_vertexbuffer = 0;
8623 rsurface.modelvertex3f_bufferoffset = 0;
8624 rsurface.modelsvector3f_vertexbuffer = 0;
8625 rsurface.modelsvector3f_bufferoffset = 0;
8626 rsurface.modeltvector3f_vertexbuffer = 0;
8627 rsurface.modeltvector3f_bufferoffset = 0;
8628 rsurface.modelnormal3f_vertexbuffer = 0;
8629 rsurface.modelnormal3f_bufferoffset = 0;
8630 rsurface.modelgeneratedvertex = true;
8631 rsurface.modellightmapcolor4f = (float *)color4f;
8632 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8633 rsurface.modellightmapcolor4f_bufferoffset = 0;
8634 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8635 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8636 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8637 rsurface.modeltexcoordlightmap2f = NULL;
8638 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8639 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8640 rsurface.modelskeletalindex4ub = NULL;
8641 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8642 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8643 rsurface.modelskeletalweight4ub = NULL;
8644 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8645 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8646 rsurface.modelelement3i = (int *)element3i;
8647 rsurface.modelelement3i_indexbuffer = NULL;
8648 rsurface.modelelement3i_bufferoffset = 0;
8649 rsurface.modelelement3s = (unsigned short *)element3s;
8650 rsurface.modelelement3s_indexbuffer = NULL;
8651 rsurface.modelelement3s_bufferoffset = 0;
8652 rsurface.modellightmapoffsets = NULL;
8653 rsurface.modelsurfaces = NULL;
8654 rsurface.batchgeneratedvertex = false;
8655 rsurface.batchfirstvertex = 0;
8656 rsurface.batchnumvertices = 0;
8657 rsurface.batchfirsttriangle = 0;
8658 rsurface.batchnumtriangles = 0;
8659 rsurface.batchvertex3f = NULL;
8660 rsurface.batchvertex3f_vertexbuffer = NULL;
8661 rsurface.batchvertex3f_bufferoffset = 0;
8662 rsurface.batchsvector3f = NULL;
8663 rsurface.batchsvector3f_vertexbuffer = NULL;
8664 rsurface.batchsvector3f_bufferoffset = 0;
8665 rsurface.batchtvector3f = NULL;
8666 rsurface.batchtvector3f_vertexbuffer = NULL;
8667 rsurface.batchtvector3f_bufferoffset = 0;
8668 rsurface.batchnormal3f = NULL;
8669 rsurface.batchnormal3f_vertexbuffer = NULL;
8670 rsurface.batchnormal3f_bufferoffset = 0;
8671 rsurface.batchlightmapcolor4f = NULL;
8672 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8673 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8674 rsurface.batchtexcoordtexture2f = NULL;
8675 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8676 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8677 rsurface.batchtexcoordlightmap2f = NULL;
8678 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8679 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8680 rsurface.batchskeletalindex4ub = NULL;
8681 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8682 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8683 rsurface.batchskeletalweight4ub = NULL;
8684 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8685 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8686 rsurface.batchvertexmesh = NULL;
8687 rsurface.batchvertexmesh_vertexbuffer = NULL;
8688 rsurface.batchvertexmesh_bufferoffset = 0;
8689 rsurface.batchelement3i = NULL;
8690 rsurface.batchelement3i_indexbuffer = NULL;
8691 rsurface.batchelement3i_bufferoffset = 0;
8692 rsurface.batchelement3s = NULL;
8693 rsurface.batchelement3s_indexbuffer = NULL;
8694 rsurface.batchelement3s_bufferoffset = 0;
8695 rsurface.passcolor4f = NULL;
8696 rsurface.passcolor4f_vertexbuffer = NULL;
8697 rsurface.passcolor4f_bufferoffset = 0;
8698 rsurface.forcecurrenttextureupdate = true;
8700 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8702 if ((wantnormals || wanttangents) && !normal3f)
8704 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8705 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8707 if (wanttangents && !svector3f)
8709 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8710 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8711 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8716 float RSurf_FogPoint(const float *v)
8718 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8719 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8720 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8721 float FogHeightFade = r_refdef.fogheightfade;
8723 unsigned int fogmasktableindex;
8724 if (r_refdef.fogplaneviewabove)
8725 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8727 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8728 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8729 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8732 float RSurf_FogVertex(const float *v)
8734 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8735 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8736 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8737 float FogHeightFade = rsurface.fogheightfade;
8739 unsigned int fogmasktableindex;
8740 if (r_refdef.fogplaneviewabove)
8741 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8743 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8744 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8745 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8748 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8751 for (i = 0;i < numelements;i++)
8752 outelement3i[i] = inelement3i[i] + adjust;
8755 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8756 extern cvar_t gl_vbo;
8757 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8765 int surfacefirsttriangle;
8766 int surfacenumtriangles;
8767 int surfacefirstvertex;
8768 int surfaceendvertex;
8769 int surfacenumvertices;
8770 int batchnumsurfaces = texturenumsurfaces;
8771 int batchnumvertices;
8772 int batchnumtriangles;
8776 qboolean dynamicvertex;
8779 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8782 q3shaderinfo_deform_t *deform;
8783 const msurface_t *surface, *firstsurface;
8784 r_vertexmesh_t *vertexmesh;
8785 if (!texturenumsurfaces)
8787 // find vertex range of this surface batch
8789 firstsurface = texturesurfacelist[0];
8790 firsttriangle = firstsurface->num_firsttriangle;
8791 batchnumvertices = 0;
8792 batchnumtriangles = 0;
8793 firstvertex = endvertex = firstsurface->num_firstvertex;
8794 for (i = 0;i < texturenumsurfaces;i++)
8796 surface = texturesurfacelist[i];
8797 if (surface != firstsurface + i)
8799 surfacefirstvertex = surface->num_firstvertex;
8800 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8801 surfacenumvertices = surface->num_vertices;
8802 surfacenumtriangles = surface->num_triangles;
8803 if (firstvertex > surfacefirstvertex)
8804 firstvertex = surfacefirstvertex;
8805 if (endvertex < surfaceendvertex)
8806 endvertex = surfaceendvertex;
8807 batchnumvertices += surfacenumvertices;
8808 batchnumtriangles += surfacenumtriangles;
8811 r_refdef.stats[r_stat_batch_batches]++;
8813 r_refdef.stats[r_stat_batch_withgaps]++;
8814 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8815 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8816 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8818 // we now know the vertex range used, and if there are any gaps in it
8819 rsurface.batchfirstvertex = firstvertex;
8820 rsurface.batchnumvertices = endvertex - firstvertex;
8821 rsurface.batchfirsttriangle = firsttriangle;
8822 rsurface.batchnumtriangles = batchnumtriangles;
8824 // this variable holds flags for which properties have been updated that
8825 // may require regenerating vertexmesh array...
8828 // check if any dynamic vertex processing must occur
8829 dynamicvertex = false;
8831 // a cvar to force the dynamic vertex path to be taken, for debugging
8832 if (r_batch_debugdynamicvertexpath.integer)
8836 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8837 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8838 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8839 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8841 dynamicvertex = true;
8844 // if there is a chance of animated vertex colors, it's a dynamic batch
8845 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8849 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8850 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8851 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8852 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8854 dynamicvertex = true;
8855 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8858 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8860 switch (deform->deform)
8863 case Q3DEFORM_PROJECTIONSHADOW:
8864 case Q3DEFORM_TEXT0:
8865 case Q3DEFORM_TEXT1:
8866 case Q3DEFORM_TEXT2:
8867 case Q3DEFORM_TEXT3:
8868 case Q3DEFORM_TEXT4:
8869 case Q3DEFORM_TEXT5:
8870 case Q3DEFORM_TEXT6:
8871 case Q3DEFORM_TEXT7:
8874 case Q3DEFORM_AUTOSPRITE:
8877 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8878 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8879 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8880 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8882 dynamicvertex = true;
8883 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8884 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8886 case Q3DEFORM_AUTOSPRITE2:
8889 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
8890 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
8891 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
8892 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
8894 dynamicvertex = true;
8895 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8896 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8898 case Q3DEFORM_NORMAL:
8901 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
8902 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
8903 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
8904 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
8906 dynamicvertex = true;
8907 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8908 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8911 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8912 break; // if wavefunc is a nop, ignore this transform
8915 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
8916 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
8917 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
8918 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
8920 dynamicvertex = true;
8921 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8922 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8924 case Q3DEFORM_BULGE:
8927 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
8928 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
8929 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
8930 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
8932 dynamicvertex = true;
8933 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8934 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8937 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8938 break; // if wavefunc is a nop, ignore this transform
8941 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
8942 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
8943 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
8944 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
8946 dynamicvertex = true;
8947 batchneed |= BATCHNEED_ARRAY_VERTEX;
8948 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8952 if (rsurface.texture->materialshaderpass)
8954 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
8957 case Q3TCGEN_TEXTURE:
8959 case Q3TCGEN_LIGHTMAP:
8962 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
8963 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
8964 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
8965 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
8967 dynamicvertex = true;
8968 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8969 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8971 case Q3TCGEN_VECTOR:
8974 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
8975 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
8976 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
8977 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
8979 dynamicvertex = true;
8980 batchneed |= BATCHNEED_ARRAY_VERTEX;
8981 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8983 case Q3TCGEN_ENVIRONMENT:
8986 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
8987 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
8988 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
8989 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
8991 dynamicvertex = true;
8992 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8993 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8996 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9000 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9001 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9002 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9003 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9005 dynamicvertex = true;
9006 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9007 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9011 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9015 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9016 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9017 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9018 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9020 dynamicvertex = true;
9021 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9024 // when the model data has no vertex buffer (dynamic mesh), we need to
9026 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9027 batchneed |= BATCHNEED_NOGAPS;
9029 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9030 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9031 // we ensure this by treating the vertex batch as dynamic...
9032 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9036 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9037 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9038 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9039 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9041 dynamicvertex = true;
9046 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9047 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9048 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9049 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9050 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9051 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9052 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9053 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9056 // if needsupdate, we have to do a dynamic vertex batch for sure
9057 if (needsupdate & batchneed)
9061 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9062 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9063 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9064 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9066 dynamicvertex = true;
9069 // see if we need to build vertexmesh from arrays
9070 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9074 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9075 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9076 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9077 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9079 dynamicvertex = true;
9082 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9083 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9084 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9086 rsurface.batchvertex3f = rsurface.modelvertex3f;
9087 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9088 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9089 rsurface.batchsvector3f = rsurface.modelsvector3f;
9090 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9091 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9092 rsurface.batchtvector3f = rsurface.modeltvector3f;
9093 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9094 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9095 rsurface.batchnormal3f = rsurface.modelnormal3f;
9096 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9097 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9098 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9099 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9100 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9101 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9102 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9103 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9104 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9105 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9106 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9107 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9108 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9109 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9110 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9111 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9112 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9113 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9114 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9115 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9116 rsurface.batchelement3i = rsurface.modelelement3i;
9117 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9118 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9119 rsurface.batchelement3s = rsurface.modelelement3s;
9120 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9121 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9122 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9123 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9124 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9125 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9126 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9128 // if any dynamic vertex processing has to occur in software, we copy the
9129 // entire surface list together before processing to rebase the vertices
9130 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9132 // if any gaps exist and we do not have a static vertex buffer, we have to
9133 // copy the surface list together to avoid wasting upload bandwidth on the
9134 // vertices in the gaps.
9136 // if gaps exist and we have a static vertex buffer, we can choose whether
9137 // to combine the index buffer ranges into one dynamic index buffer or
9138 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9140 // in many cases the batch is reduced to one draw call.
9142 rsurface.batchmultidraw = false;
9143 rsurface.batchmultidrawnumsurfaces = 0;
9144 rsurface.batchmultidrawsurfacelist = NULL;
9148 // static vertex data, just set pointers...
9149 rsurface.batchgeneratedvertex = false;
9150 // if there are gaps, we want to build a combined index buffer,
9151 // otherwise use the original static buffer with an appropriate offset
9154 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9155 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9156 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9157 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9158 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9160 rsurface.batchmultidraw = true;
9161 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9162 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9165 // build a new triangle elements array for this batch
9166 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9167 rsurface.batchfirsttriangle = 0;
9169 for (i = 0;i < texturenumsurfaces;i++)
9171 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9172 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9173 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9174 numtriangles += surfacenumtriangles;
9176 rsurface.batchelement3i_indexbuffer = NULL;
9177 rsurface.batchelement3i_bufferoffset = 0;
9178 rsurface.batchelement3s = NULL;
9179 rsurface.batchelement3s_indexbuffer = NULL;
9180 rsurface.batchelement3s_bufferoffset = 0;
9181 if (endvertex <= 65536)
9183 // make a 16bit (unsigned short) index array if possible
9184 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9185 for (i = 0;i < numtriangles*3;i++)
9186 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9188 // upload buffer data for the copytriangles batch
9189 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9191 if (rsurface.batchelement3s)
9192 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9193 else if (rsurface.batchelement3i)
9194 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9199 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9200 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9201 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9202 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9207 // something needs software processing, do it for real...
9208 // we only directly handle separate array data in this case and then
9209 // generate interleaved data if needed...
9210 rsurface.batchgeneratedvertex = true;
9211 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9212 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9213 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9214 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9216 // now copy the vertex data into a combined array and make an index array
9217 // (this is what Quake3 does all the time)
9218 // we also apply any skeletal animation here that would have been done in
9219 // the vertex shader, because most of the dynamic vertex animation cases
9220 // need actual vertex positions and normals
9221 //if (dynamicvertex)
9223 rsurface.batchvertexmesh = NULL;
9224 rsurface.batchvertexmesh_vertexbuffer = NULL;
9225 rsurface.batchvertexmesh_bufferoffset = 0;
9226 rsurface.batchvertex3f = NULL;
9227 rsurface.batchvertex3f_vertexbuffer = NULL;
9228 rsurface.batchvertex3f_bufferoffset = 0;
9229 rsurface.batchsvector3f = NULL;
9230 rsurface.batchsvector3f_vertexbuffer = NULL;
9231 rsurface.batchsvector3f_bufferoffset = 0;
9232 rsurface.batchtvector3f = NULL;
9233 rsurface.batchtvector3f_vertexbuffer = NULL;
9234 rsurface.batchtvector3f_bufferoffset = 0;
9235 rsurface.batchnormal3f = NULL;
9236 rsurface.batchnormal3f_vertexbuffer = NULL;
9237 rsurface.batchnormal3f_bufferoffset = 0;
9238 rsurface.batchlightmapcolor4f = NULL;
9239 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9240 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9241 rsurface.batchtexcoordtexture2f = NULL;
9242 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9243 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9244 rsurface.batchtexcoordlightmap2f = NULL;
9245 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9246 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9247 rsurface.batchskeletalindex4ub = NULL;
9248 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9249 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9250 rsurface.batchskeletalweight4ub = NULL;
9251 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9252 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9253 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9254 rsurface.batchelement3i_indexbuffer = NULL;
9255 rsurface.batchelement3i_bufferoffset = 0;
9256 rsurface.batchelement3s = NULL;
9257 rsurface.batchelement3s_indexbuffer = NULL;
9258 rsurface.batchelement3s_bufferoffset = 0;
9259 rsurface.batchskeletaltransform3x4buffer = NULL;
9260 rsurface.batchskeletaltransform3x4offset = 0;
9261 rsurface.batchskeletaltransform3x4size = 0;
9262 // we'll only be setting up certain arrays as needed
9263 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9264 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9265 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9266 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9267 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9268 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9269 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9271 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9272 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9274 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9275 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9276 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9277 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9278 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9279 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9280 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9282 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9283 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9287 for (i = 0;i < texturenumsurfaces;i++)
9289 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9290 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9291 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9292 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9293 // copy only the data requested
9294 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9295 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9296 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9298 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9300 if (rsurface.batchvertex3f)
9301 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9303 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9305 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9307 if (rsurface.modelnormal3f)
9308 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9310 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9312 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9314 if (rsurface.modelsvector3f)
9316 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9317 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9321 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9322 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9325 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9327 if (rsurface.modellightmapcolor4f)
9328 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9330 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9332 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9334 if (rsurface.modeltexcoordtexture2f)
9335 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9337 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9339 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9341 if (rsurface.modeltexcoordlightmap2f)
9342 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9344 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9346 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9348 if (rsurface.modelskeletalindex4ub)
9350 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9351 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9355 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9356 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9357 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9358 for (j = 0;j < surfacenumvertices;j++)
9363 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9364 numvertices += surfacenumvertices;
9365 numtriangles += surfacenumtriangles;
9368 // generate a 16bit index array as well if possible
9369 // (in general, dynamic batches fit)
9370 if (numvertices <= 65536)
9372 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9373 for (i = 0;i < numtriangles*3;i++)
9374 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9377 // since we've copied everything, the batch now starts at 0
9378 rsurface.batchfirstvertex = 0;
9379 rsurface.batchnumvertices = batchnumvertices;
9380 rsurface.batchfirsttriangle = 0;
9381 rsurface.batchnumtriangles = batchnumtriangles;
9384 // apply skeletal animation that would have been done in the vertex shader
9385 if (rsurface.batchskeletaltransform3x4)
9387 const unsigned char *si;
9388 const unsigned char *sw;
9390 const float *b = rsurface.batchskeletaltransform3x4;
9391 float *vp, *vs, *vt, *vn;
9393 float m[3][4], n[3][4];
9394 float tp[3], ts[3], tt[3], tn[3];
9395 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9396 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9397 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9398 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9399 si = rsurface.batchskeletalindex4ub;
9400 sw = rsurface.batchskeletalweight4ub;
9401 vp = rsurface.batchvertex3f;
9402 vs = rsurface.batchsvector3f;
9403 vt = rsurface.batchtvector3f;
9404 vn = rsurface.batchnormal3f;
9405 memset(m[0], 0, sizeof(m));
9406 memset(n[0], 0, sizeof(n));
9407 for (i = 0;i < batchnumvertices;i++)
9409 t[0] = b + si[0]*12;
9412 // common case - only one matrix
9426 else if (sw[2] + sw[3])
9429 t[1] = b + si[1]*12;
9430 t[2] = b + si[2]*12;
9431 t[3] = b + si[3]*12;
9432 w[0] = sw[0] * (1.0f / 255.0f);
9433 w[1] = sw[1] * (1.0f / 255.0f);
9434 w[2] = sw[2] * (1.0f / 255.0f);
9435 w[3] = sw[3] * (1.0f / 255.0f);
9436 // blend the matrices
9437 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9438 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9439 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9440 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9441 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9442 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9443 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9444 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9445 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9446 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9447 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9448 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9453 t[1] = b + si[1]*12;
9454 w[0] = sw[0] * (1.0f / 255.0f);
9455 w[1] = sw[1] * (1.0f / 255.0f);
9456 // blend the matrices
9457 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9458 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9459 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9460 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9461 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9462 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9463 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9464 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9465 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9466 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9467 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9468 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9472 // modify the vertex
9474 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9475 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9476 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9480 // the normal transformation matrix is a set of cross products...
9481 CrossProduct(m[1], m[2], n[0]);
9482 CrossProduct(m[2], m[0], n[1]);
9483 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9485 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9486 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9487 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9488 VectorNormalize(vn);
9493 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9494 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9495 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9496 VectorNormalize(vs);
9499 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9500 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9501 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9502 VectorNormalize(vt);
9507 rsurface.batchskeletaltransform3x4 = NULL;
9508 rsurface.batchskeletalnumtransforms = 0;
9511 // q1bsp surfaces rendered in vertex color mode have to have colors
9512 // calculated based on lightstyles
9513 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9515 // generate color arrays for the surfaces in this list
9520 const unsigned char *lm;
9521 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9522 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9523 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9525 for (i = 0;i < texturenumsurfaces;i++)
9527 surface = texturesurfacelist[i];
9528 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9529 surfacenumvertices = surface->num_vertices;
9530 if (surface->lightmapinfo->samples)
9532 for (j = 0;j < surfacenumvertices;j++)
9534 lm = surface->lightmapinfo->samples + offsets[j];
9535 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9536 VectorScale(lm, scale, c);
9537 if (surface->lightmapinfo->styles[1] != 255)
9539 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9541 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9542 VectorMA(c, scale, lm, c);
9543 if (surface->lightmapinfo->styles[2] != 255)
9546 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9547 VectorMA(c, scale, lm, c);
9548 if (surface->lightmapinfo->styles[3] != 255)
9551 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9552 VectorMA(c, scale, lm, c);
9559 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
9565 for (j = 0;j < surfacenumvertices;j++)
9567 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9574 // if vertices are deformed (sprite flares and things in maps, possibly
9575 // water waves, bulges and other deformations), modify the copied vertices
9577 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9580 switch (deform->deform)
9583 case Q3DEFORM_PROJECTIONSHADOW:
9584 case Q3DEFORM_TEXT0:
9585 case Q3DEFORM_TEXT1:
9586 case Q3DEFORM_TEXT2:
9587 case Q3DEFORM_TEXT3:
9588 case Q3DEFORM_TEXT4:
9589 case Q3DEFORM_TEXT5:
9590 case Q3DEFORM_TEXT6:
9591 case Q3DEFORM_TEXT7:
9594 case Q3DEFORM_AUTOSPRITE:
9595 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9596 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9597 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9598 VectorNormalize(newforward);
9599 VectorNormalize(newright);
9600 VectorNormalize(newup);
9601 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9602 // rsurface.batchvertex3f_vertexbuffer = NULL;
9603 // rsurface.batchvertex3f_bufferoffset = 0;
9604 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9605 // rsurface.batchsvector3f_vertexbuffer = NULL;
9606 // rsurface.batchsvector3f_bufferoffset = 0;
9607 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9608 // rsurface.batchtvector3f_vertexbuffer = NULL;
9609 // rsurface.batchtvector3f_bufferoffset = 0;
9610 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9611 // rsurface.batchnormal3f_vertexbuffer = NULL;
9612 // rsurface.batchnormal3f_bufferoffset = 0;
9613 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9614 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9615 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9616 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9617 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9618 // a single autosprite surface can contain multiple sprites...
9619 for (j = 0;j < batchnumvertices - 3;j += 4)
9621 VectorClear(center);
9622 for (i = 0;i < 4;i++)
9623 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9624 VectorScale(center, 0.25f, center);
9625 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9626 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9627 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9628 for (i = 0;i < 4;i++)
9630 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9631 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9634 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9635 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9636 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9638 case Q3DEFORM_AUTOSPRITE2:
9639 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9640 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9641 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9642 VectorNormalize(newforward);
9643 VectorNormalize(newright);
9644 VectorNormalize(newup);
9645 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9646 // rsurface.batchvertex3f_vertexbuffer = NULL;
9647 // rsurface.batchvertex3f_bufferoffset = 0;
9649 const float *v1, *v2;
9659 memset(shortest, 0, sizeof(shortest));
9660 // a single autosprite surface can contain multiple sprites...
9661 for (j = 0;j < batchnumvertices - 3;j += 4)
9663 VectorClear(center);
9664 for (i = 0;i < 4;i++)
9665 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9666 VectorScale(center, 0.25f, center);
9667 // find the two shortest edges, then use them to define the
9668 // axis vectors for rotating around the central axis
9669 for (i = 0;i < 6;i++)
9671 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9672 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9673 l = VectorDistance2(v1, v2);
9674 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9676 l += (1.0f / 1024.0f);
9677 if (shortest[0].length2 > l || i == 0)
9679 shortest[1] = shortest[0];
9680 shortest[0].length2 = l;
9681 shortest[0].v1 = v1;
9682 shortest[0].v2 = v2;
9684 else if (shortest[1].length2 > l || i == 1)
9686 shortest[1].length2 = l;
9687 shortest[1].v1 = v1;
9688 shortest[1].v2 = v2;
9691 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9692 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9693 // this calculates the right vector from the shortest edge
9694 // and the up vector from the edge midpoints
9695 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9696 VectorNormalize(right);
9697 VectorSubtract(end, start, up);
9698 VectorNormalize(up);
9699 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9700 VectorSubtract(rsurface.localvieworigin, center, forward);
9701 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9702 VectorNegate(forward, forward);
9703 VectorReflect(forward, 0, up, forward);
9704 VectorNormalize(forward);
9705 CrossProduct(up, forward, newright);
9706 VectorNormalize(newright);
9707 // rotate the quad around the up axis vector, this is made
9708 // especially easy by the fact we know the quad is flat,
9709 // so we only have to subtract the center position and
9710 // measure distance along the right vector, and then
9711 // multiply that by the newright vector and add back the
9713 // we also need to subtract the old position to undo the
9714 // displacement from the center, which we do with a
9715 // DotProduct, the subtraction/addition of center is also
9716 // optimized into DotProducts here
9717 l = DotProduct(right, center);
9718 for (i = 0;i < 4;i++)
9720 v1 = rsurface.batchvertex3f + 3*(j+i);
9721 f = DotProduct(right, v1) - l;
9722 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9726 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9728 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9729 // rsurface.batchnormal3f_vertexbuffer = NULL;
9730 // rsurface.batchnormal3f_bufferoffset = 0;
9731 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9733 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9735 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9736 // rsurface.batchsvector3f_vertexbuffer = NULL;
9737 // rsurface.batchsvector3f_bufferoffset = 0;
9738 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9739 // rsurface.batchtvector3f_vertexbuffer = NULL;
9740 // rsurface.batchtvector3f_bufferoffset = 0;
9741 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9744 case Q3DEFORM_NORMAL:
9745 // deform the normals to make reflections wavey
9746 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9747 rsurface.batchnormal3f_vertexbuffer = NULL;
9748 rsurface.batchnormal3f_bufferoffset = 0;
9749 for (j = 0;j < batchnumvertices;j++)
9752 float *normal = rsurface.batchnormal3f + 3*j;
9753 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9754 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9755 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9756 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9757 VectorNormalize(normal);
9759 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9761 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9762 // rsurface.batchsvector3f_vertexbuffer = NULL;
9763 // rsurface.batchsvector3f_bufferoffset = 0;
9764 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9765 // rsurface.batchtvector3f_vertexbuffer = NULL;
9766 // rsurface.batchtvector3f_bufferoffset = 0;
9767 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9771 // deform vertex array to make wavey water and flags and such
9772 waveparms[0] = deform->waveparms[0];
9773 waveparms[1] = deform->waveparms[1];
9774 waveparms[2] = deform->waveparms[2];
9775 waveparms[3] = deform->waveparms[3];
9776 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9777 break; // if wavefunc is a nop, don't make a dynamic vertex array
9778 // this is how a divisor of vertex influence on deformation
9779 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9780 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9781 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9782 // rsurface.batchvertex3f_vertexbuffer = NULL;
9783 // rsurface.batchvertex3f_bufferoffset = 0;
9784 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9785 // rsurface.batchnormal3f_vertexbuffer = NULL;
9786 // rsurface.batchnormal3f_bufferoffset = 0;
9787 for (j = 0;j < batchnumvertices;j++)
9789 // if the wavefunc depends on time, evaluate it per-vertex
9792 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9793 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9795 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9797 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9798 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9799 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9801 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9802 // rsurface.batchsvector3f_vertexbuffer = NULL;
9803 // rsurface.batchsvector3f_bufferoffset = 0;
9804 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9805 // rsurface.batchtvector3f_vertexbuffer = NULL;
9806 // rsurface.batchtvector3f_bufferoffset = 0;
9807 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9810 case Q3DEFORM_BULGE:
9811 // deform vertex array to make the surface have moving bulges
9812 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9813 // rsurface.batchvertex3f_vertexbuffer = NULL;
9814 // rsurface.batchvertex3f_bufferoffset = 0;
9815 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9816 // rsurface.batchnormal3f_vertexbuffer = NULL;
9817 // rsurface.batchnormal3f_bufferoffset = 0;
9818 for (j = 0;j < batchnumvertices;j++)
9820 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9821 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9823 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9824 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9825 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9827 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9828 // rsurface.batchsvector3f_vertexbuffer = NULL;
9829 // rsurface.batchsvector3f_bufferoffset = 0;
9830 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9831 // rsurface.batchtvector3f_vertexbuffer = NULL;
9832 // rsurface.batchtvector3f_bufferoffset = 0;
9833 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9837 // deform vertex array
9838 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9839 break; // if wavefunc is a nop, don't make a dynamic vertex array
9840 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9841 VectorScale(deform->parms, scale, waveparms);
9842 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9843 // rsurface.batchvertex3f_vertexbuffer = NULL;
9844 // rsurface.batchvertex3f_bufferoffset = 0;
9845 for (j = 0;j < batchnumvertices;j++)
9846 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9851 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9853 // generate texcoords based on the chosen texcoord source
9854 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9857 case Q3TCGEN_TEXTURE:
9859 case Q3TCGEN_LIGHTMAP:
9860 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9861 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9862 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9863 if (rsurface.batchtexcoordlightmap2f)
9864 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9866 case Q3TCGEN_VECTOR:
9867 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9868 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9869 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9870 for (j = 0;j < batchnumvertices;j++)
9872 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
9873 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
9876 case Q3TCGEN_ENVIRONMENT:
9877 // make environment reflections using a spheremap
9878 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9879 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9880 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9881 for (j = 0;j < batchnumvertices;j++)
9883 // identical to Q3A's method, but executed in worldspace so
9884 // carried models can be shiny too
9886 float viewer[3], d, reflected[3], worldreflected[3];
9888 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9889 // VectorNormalize(viewer);
9891 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9893 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9894 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9895 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9896 // note: this is proportinal to viewer, so we can normalize later
9898 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9899 VectorNormalize(worldreflected);
9901 // note: this sphere map only uses world x and z!
9902 // so positive and negative y will LOOK THE SAME.
9903 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9904 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9908 // the only tcmod that needs software vertex processing is turbulent, so
9909 // check for it here and apply the changes if needed
9910 // and we only support that as the first one
9911 // (handling a mixture of turbulent and other tcmods would be problematic
9912 // without punting it entirely to a software path)
9913 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9915 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
9916 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
9917 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9918 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9919 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9920 for (j = 0;j < batchnumvertices;j++)
9922 rsurface.batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9923 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9928 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9930 // convert the modified arrays to vertex structs
9931 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9932 // rsurface.batchvertexmesh_vertexbuffer = NULL;
9933 // rsurface.batchvertexmesh_bufferoffset = 0;
9934 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9935 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9936 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9937 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9938 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9939 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9940 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9942 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9944 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9945 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9948 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9949 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9950 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9951 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9952 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9953 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9954 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9955 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9956 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9957 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9959 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9961 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9962 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9967 // upload buffer data for the dynamic batch
9968 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9970 if (rsurface.batchvertexmesh)
9971 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
9974 if (rsurface.batchvertex3f)
9975 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
9976 if (rsurface.batchsvector3f)
9977 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
9978 if (rsurface.batchtvector3f)
9979 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
9980 if (rsurface.batchnormal3f)
9981 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
9982 if (rsurface.batchlightmapcolor4f)
9983 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
9984 if (rsurface.batchtexcoordtexture2f)
9985 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
9986 if (rsurface.batchtexcoordlightmap2f)
9987 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
9988 if (rsurface.batchskeletalindex4ub)
9989 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
9990 if (rsurface.batchskeletalweight4ub)
9991 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
9993 if (rsurface.batchelement3s)
9994 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9995 else if (rsurface.batchelement3i)
9996 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10000 void RSurf_DrawBatch(void)
10002 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10003 // through the pipeline, killing it earlier in the pipeline would have
10004 // per-surface overhead rather than per-batch overhead, so it's best to
10005 // reject it here, before it hits glDraw.
10006 if (rsurface.batchnumtriangles == 0)
10009 // batch debugging code
10010 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10016 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10017 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10020 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10022 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10024 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10025 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
10032 if (rsurface.batchmultidraw)
10034 // issue multiple draws rather than copying index data
10035 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10036 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10037 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10038 for (i = 0;i < numsurfaces;)
10040 // combine consecutive surfaces as one draw
10041 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10042 if (surfacelist[j] != surfacelist[k] + 1)
10044 firstvertex = surfacelist[i]->num_firstvertex;
10045 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10046 firsttriangle = surfacelist[i]->num_firsttriangle;
10047 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10048 R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
10054 // there is only one consecutive run of index data (may have been combined)
10055 R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
10059 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10061 // pick the closest matching water plane
10062 int planeindex, vertexindex, bestplaneindex = -1;
10066 r_waterstate_waterplane_t *p;
10067 qboolean prepared = false;
10069 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10071 if(p->camera_entity != rsurface.texture->camera_entity)
10076 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10078 if(rsurface.batchnumvertices == 0)
10081 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10083 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10084 d += fabs(PlaneDiff(vert, &p->plane));
10086 if (bestd > d || bestplaneindex < 0)
10089 bestplaneindex = planeindex;
10092 return bestplaneindex;
10093 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10094 // this situation though, as it might be better to render single larger
10095 // batches with useless stuff (backface culled for example) than to
10096 // render multiple smaller batches
10099 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10102 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10103 rsurface.passcolor4f_vertexbuffer = 0;
10104 rsurface.passcolor4f_bufferoffset = 0;
10105 for (i = 0;i < rsurface.batchnumvertices;i++)
10106 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10109 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10116 if (rsurface.passcolor4f)
10118 // generate color arrays
10119 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10120 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10121 rsurface.passcolor4f_vertexbuffer = 0;
10122 rsurface.passcolor4f_bufferoffset = 0;
10123 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10125 f = RSurf_FogVertex(v);
10134 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10135 rsurface.passcolor4f_vertexbuffer = 0;
10136 rsurface.passcolor4f_bufferoffset = 0;
10137 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10139 f = RSurf_FogVertex(v);
10148 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10155 if (!rsurface.passcolor4f)
10157 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10158 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10159 rsurface.passcolor4f_vertexbuffer = 0;
10160 rsurface.passcolor4f_bufferoffset = 0;
10161 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10163 f = RSurf_FogVertex(v);
10164 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10165 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10166 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10171 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10176 if (!rsurface.passcolor4f)
10178 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10179 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10180 rsurface.passcolor4f_vertexbuffer = 0;
10181 rsurface.passcolor4f_bufferoffset = 0;
10182 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10191 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10196 if (!rsurface.passcolor4f)
10198 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10199 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10200 rsurface.passcolor4f_vertexbuffer = 0;
10201 rsurface.passcolor4f_bufferoffset = 0;
10202 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10204 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10205 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10206 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10211 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10214 rsurface.passcolor4f = NULL;
10215 rsurface.passcolor4f_vertexbuffer = 0;
10216 rsurface.passcolor4f_bufferoffset = 0;
10217 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10218 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10219 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10220 GL_Color(r, g, b, a);
10221 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10222 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10223 R_Mesh_TexMatrix(0, NULL);
10227 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10229 // TODO: optimize applyfog && applycolor case
10230 // just apply fog if necessary, and tint the fog color array if necessary
10231 rsurface.passcolor4f = NULL;
10232 rsurface.passcolor4f_vertexbuffer = 0;
10233 rsurface.passcolor4f_bufferoffset = 0;
10234 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10235 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10236 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10237 GL_Color(r, g, b, a);
10241 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10244 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10245 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10246 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10247 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10248 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10249 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10250 GL_Color(r, g, b, a);
10254 static void RSurf_DrawBatch_GL11_ClampColor(void)
10259 if (!rsurface.passcolor4f)
10261 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10263 c2[0] = bound(0.0f, c1[0], 1.0f);
10264 c2[1] = bound(0.0f, c1[1], 1.0f);
10265 c2[2] = bound(0.0f, c1[2], 1.0f);
10266 c2[3] = bound(0.0f, c1[3], 1.0f);
10270 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10280 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10281 rsurface.passcolor4f_vertexbuffer = 0;
10282 rsurface.passcolor4f_bufferoffset = 0;
10283 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10285 f = -DotProduct(r_refdef.view.forward, n);
10287 f = f * 0.85 + 0.15; // work around so stuff won't get black
10288 f *= fakelightintensity;
10289 Vector4Set(c, f, f, f, 1);
10293 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10295 RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10296 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10297 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10298 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10299 GL_Color(r, g, b, a);
10303 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10311 vec3_t ambientcolor;
10312 vec3_t diffusecolor;
10316 VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10317 f = 0.5f * lightmapintensity;
10318 ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10319 ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10320 ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10321 diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10322 diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10323 diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10325 if (VectorLength2(diffusecolor) > 0)
10327 // q3-style directional shading
10328 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10329 rsurface.passcolor4f_vertexbuffer = 0;
10330 rsurface.passcolor4f_bufferoffset = 0;
10331 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
10333 if ((f = DotProduct(n, lightdir)) > 0)
10334 VectorMA(ambientcolor, f, diffusecolor, c);
10336 VectorCopy(ambientcolor, c);
10343 *applycolor = false;
10347 *r = ambientcolor[0];
10348 *g = ambientcolor[1];
10349 *b = ambientcolor[2];
10350 rsurface.passcolor4f = NULL;
10351 rsurface.passcolor4f_vertexbuffer = 0;
10352 rsurface.passcolor4f_bufferoffset = 0;
10356 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10358 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10359 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10360 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10361 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10362 GL_Color(r, g, b, a);
10366 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10374 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10375 rsurface.passcolor4f_vertexbuffer = 0;
10376 rsurface.passcolor4f_bufferoffset = 0;
10378 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10380 f = 1 - RSurf_FogVertex(v);
10388 void RSurf_SetupDepthAndCulling(void)
10390 // submodels are biased to avoid z-fighting with world surfaces that they
10391 // may be exactly overlapping (avoids z-fighting artifacts on certain
10392 // doors and things in Quake maps)
10393 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10394 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10395 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10396 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10399 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10402 // transparent sky would be ridiculous
10403 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10405 R_SetupShader_Generic_NoTexture(false, false);
10406 skyrenderlater = true;
10407 RSurf_SetupDepthAndCulling();
10408 GL_DepthMask(true);
10410 // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10411 if (r_sky_scissor.integer)
10413 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10414 for (i = 0; i < texturenumsurfaces; i++)
10416 const msurface_t *surf = texturesurfacelist[i];
10419 float mins[3], maxs[3];
10421 for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10423 Matrix4x4_Transform(&rsurface.matrix, v, p);
10426 if (mins[0] > p[0]) mins[0] = p[0];
10427 if (mins[1] > p[1]) mins[1] = p[1];
10428 if (mins[2] > p[2]) mins[2] = p[2];
10429 if (maxs[0] < p[0]) maxs[0] = p[0];
10430 if (maxs[1] < p[1]) maxs[1] = p[1];
10431 if (maxs[2] < p[2]) maxs[2] = p[2];
10435 VectorCopy(p, mins);
10436 VectorCopy(p, maxs);
10439 if (!R_ScissorForBBox(mins, maxs, scissor))
10443 if (skyscissor[0] > scissor[0])
10445 skyscissor[2] += skyscissor[0] - scissor[0];
10446 skyscissor[0] = scissor[0];
10448 if (skyscissor[1] > scissor[1])
10450 skyscissor[3] += skyscissor[1] - scissor[1];
10451 skyscissor[1] = scissor[1];
10453 if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10454 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10455 if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10456 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10459 Vector4Copy(scissor, skyscissor);
10464 // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10465 // skymasking on them, and Quake3 never did sky masking (unlike
10466 // software Quake and software Quake2), so disable the sky masking
10467 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10468 // and skymasking also looks very bad when noclipping outside the
10469 // level, so don't use it then either.
10470 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10472 R_Mesh_ResetTextureState();
10473 if (skyrendermasked)
10475 R_SetupShader_DepthOrShadow(false, false, false);
10476 // depth-only (masking)
10477 GL_ColorMask(0, 0, 0, 0);
10478 // just to make sure that braindead drivers don't draw
10479 // anything despite that colormask...
10480 GL_BlendFunc(GL_ZERO, GL_ONE);
10481 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10482 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10486 R_SetupShader_Generic_NoTexture(false, false);
10488 GL_BlendFunc(GL_ONE, GL_ZERO);
10489 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10490 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10491 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10494 if (skyrendermasked)
10495 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10497 R_Mesh_ResetTextureState();
10498 GL_Color(1, 1, 1, 1);
10501 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10502 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10503 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10505 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10509 // render screenspace normalmap to texture
10510 GL_DepthMask(true);
10511 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10516 // bind lightmap texture
10518 // water/refraction/reflection/camera surfaces have to be handled specially
10519 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10521 int start, end, startplaneindex;
10522 for (start = 0;start < texturenumsurfaces;start = end)
10524 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10525 if(startplaneindex < 0)
10527 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10528 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10532 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10534 // now that we have a batch using the same planeindex, render it
10535 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10537 // render water or distortion background
10538 GL_DepthMask(true);
10539 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10541 // blend surface on top
10542 GL_DepthMask(false);
10543 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10546 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10548 // render surface with reflection texture as input
10549 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10550 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10557 // render surface batch normally
10558 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10559 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10563 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10565 // OpenGL 1.3 path - anything not completely ancient
10566 qboolean applycolor;
10569 const texturelayer_t *layer;
10570 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10571 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10573 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10576 int layertexrgbscale;
10577 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10579 if (layerindex == 0)
10580 GL_AlphaTest(true);
10583 GL_AlphaTest(false);
10584 GL_DepthFunc(GL_EQUAL);
10587 GL_DepthMask(layer->depthmask && writedepth);
10588 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10589 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10591 layertexrgbscale = 4;
10592 VectorScale(layer->color, 0.25f, layercolor);
10594 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10596 layertexrgbscale = 2;
10597 VectorScale(layer->color, 0.5f, layercolor);
10601 layertexrgbscale = 1;
10602 VectorScale(layer->color, 1.0f, layercolor);
10604 layercolor[3] = layer->color[3];
10605 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10606 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10607 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10608 switch (layer->type)
10610 case TEXTURELAYERTYPE_LITTEXTURE:
10611 // single-pass lightmapped texture with 2x rgbscale
10612 R_Mesh_TexBind(0, r_texture_white);
10613 R_Mesh_TexMatrix(0, NULL);
10614 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10615 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10616 R_Mesh_TexBind(1, layer->texture);
10617 R_Mesh_TexMatrix(1, &layer->texmatrix);
10618 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10619 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10620 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10621 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10622 else if (FAKELIGHT_ENABLED)
10623 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10624 else if (rsurface.uselightmaptexture)
10625 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10627 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10629 case TEXTURELAYERTYPE_TEXTURE:
10630 // singletexture unlit texture with transparency support
10631 R_Mesh_TexBind(0, layer->texture);
10632 R_Mesh_TexMatrix(0, &layer->texmatrix);
10633 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10634 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10635 R_Mesh_TexBind(1, 0);
10636 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10637 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10639 case TEXTURELAYERTYPE_FOG:
10640 // singletexture fogging
10641 if (layer->texture)
10643 R_Mesh_TexBind(0, layer->texture);
10644 R_Mesh_TexMatrix(0, &layer->texmatrix);
10645 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10646 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10650 R_Mesh_TexBind(0, 0);
10651 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10653 R_Mesh_TexBind(1, 0);
10654 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10655 // generate a color array for the fog pass
10656 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10657 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10661 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10664 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10666 GL_DepthFunc(GL_LEQUAL);
10667 GL_AlphaTest(false);
10671 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10673 // OpenGL 1.1 - crusty old voodoo path
10676 const texturelayer_t *layer;
10677 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10678 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10680 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10682 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10684 if (layerindex == 0)
10685 GL_AlphaTest(true);
10688 GL_AlphaTest(false);
10689 GL_DepthFunc(GL_EQUAL);
10692 GL_DepthMask(layer->depthmask && writedepth);
10693 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10694 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10695 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10696 switch (layer->type)
10698 case TEXTURELAYERTYPE_LITTEXTURE:
10699 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10701 // two-pass lit texture with 2x rgbscale
10702 // first the lightmap pass
10703 R_Mesh_TexBind(0, r_texture_white);
10704 R_Mesh_TexMatrix(0, NULL);
10705 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10706 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10707 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10708 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10709 else if (FAKELIGHT_ENABLED)
10710 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10711 else if (rsurface.uselightmaptexture)
10712 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10714 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10715 // then apply the texture to it
10716 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10717 R_Mesh_TexBind(0, layer->texture);
10718 R_Mesh_TexMatrix(0, &layer->texmatrix);
10719 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10720 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10721 RSurf_DrawBatch_GL11_Unlit(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);
10725 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10726 R_Mesh_TexBind(0, layer->texture);
10727 R_Mesh_TexMatrix(0, &layer->texmatrix);
10728 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10729 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10730 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10731 RSurf_DrawBatch_GL11_VertexShade(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);
10732 else if (FAKELIGHT_ENABLED)
10733 RSurf_DrawBatch_GL11_FakeLight(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);
10735 RSurf_DrawBatch_GL11_VertexColor(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);
10738 case TEXTURELAYERTYPE_TEXTURE:
10739 // singletexture unlit texture with transparency support
10740 R_Mesh_TexBind(0, layer->texture);
10741 R_Mesh_TexMatrix(0, &layer->texmatrix);
10742 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10743 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10744 RSurf_DrawBatch_GL11_Unlit(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);
10746 case TEXTURELAYERTYPE_FOG:
10747 // singletexture fogging
10748 if (layer->texture)
10750 R_Mesh_TexBind(0, layer->texture);
10751 R_Mesh_TexMatrix(0, &layer->texmatrix);
10752 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10753 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10757 R_Mesh_TexBind(0, 0);
10758 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10760 // generate a color array for the fog pass
10761 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10762 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10766 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10769 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10771 GL_DepthFunc(GL_LEQUAL);
10772 GL_AlphaTest(false);
10776 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10780 r_vertexgeneric_t *batchvertex;
10782 texture_t *t = rsurface.texture;
10784 // R_Mesh_ResetTextureState();
10785 R_SetupShader_Generic_NoTexture(false, false);
10787 if(t && t->currentskinframe)
10789 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10790 c[3] *= t->currentalpha;
10800 if (t->pantstexture || t->shirttexture)
10802 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10803 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10804 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10807 // brighten it up (as texture value 127 means "unlit")
10808 c[0] *= 2 * r_refdef.view.colorscale;
10809 c[1] *= 2 * r_refdef.view.colorscale;
10810 c[2] *= 2 * r_refdef.view.colorscale;
10812 if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10813 c[3] *= r_wateralpha.value;
10815 if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10817 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10818 GL_DepthMask(false);
10820 else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10822 GL_BlendFunc(GL_ONE, GL_ONE);
10823 GL_DepthMask(false);
10825 else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10827 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10828 GL_DepthMask(false);
10830 else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10832 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10833 GL_DepthMask(false);
10837 GL_BlendFunc(GL_ONE, GL_ZERO);
10838 GL_DepthMask(writedepth);
10841 if (r_showsurfaces.integer == 3)
10843 rsurface.passcolor4f = NULL;
10845 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10847 qboolean applycolor = true;
10850 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10852 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10854 else if (FAKELIGHT_ENABLED)
10856 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10858 RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10862 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10864 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10865 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10866 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10867 RSurf_DrawBatch_GL11_ApplyAmbient();
10870 if(!rsurface.passcolor4f)
10871 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10873 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10874 if(r_refdef.fogenabled)
10875 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10876 RSurf_DrawBatch_GL11_ClampColor();
10878 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10879 R_SetupShader_Generic_NoTexture(false, false);
10882 else if (!r_refdef.view.showdebug)
10884 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10885 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10886 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10888 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10889 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10891 R_Mesh_PrepareVertices_Generic_Unlock();
10894 else if (r_showsurfaces.integer == 4)
10896 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10897 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10898 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10900 unsigned char d = (vi << 3) * (1.0f / 256.0f);
10901 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10902 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
10904 R_Mesh_PrepareVertices_Generic_Unlock();
10907 else if (r_showsurfaces.integer == 2)
10910 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10911 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10912 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10914 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10915 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10916 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10917 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10918 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
10919 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
10920 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
10922 R_Mesh_PrepareVertices_Generic_Unlock();
10923 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10927 int texturesurfaceindex;
10929 const msurface_t *surface;
10930 float surfacecolor4f[4];
10931 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10932 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10934 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10936 surface = texturesurfacelist[texturesurfaceindex];
10937 k = (int)(((size_t)surface) / sizeof(msurface_t));
10938 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10939 for (j = 0;j < surface->num_vertices;j++)
10941 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10942 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10946 R_Mesh_PrepareVertices_Generic_Unlock();
10951 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10954 RSurf_SetupDepthAndCulling();
10955 if (r_showsurfaces.integer)
10957 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10960 switch (vid.renderpath)
10962 case RENDERPATH_GL20:
10963 case RENDERPATH_D3D9:
10964 case RENDERPATH_D3D10:
10965 case RENDERPATH_D3D11:
10966 case RENDERPATH_SOFT:
10967 case RENDERPATH_GLES2:
10968 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10970 case RENDERPATH_GL13:
10971 case RENDERPATH_GLES1:
10972 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10974 case RENDERPATH_GL11:
10975 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10981 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10984 int texturenumsurfaces, endsurface;
10985 texture_t *texture;
10986 const msurface_t *surface;
10987 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10989 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10990 RSurf_ActiveModelEntity(ent, false, false, false);
10993 switch (vid.renderpath)
10995 case RENDERPATH_GL20:
10996 case RENDERPATH_D3D9:
10997 case RENDERPATH_D3D10:
10998 case RENDERPATH_D3D11:
10999 case RENDERPATH_SOFT:
11000 case RENDERPATH_GLES2:
11001 RSurf_ActiveModelEntity(ent, true, true, false);
11003 case RENDERPATH_GL11:
11004 case RENDERPATH_GL13:
11005 case RENDERPATH_GLES1:
11006 RSurf_ActiveModelEntity(ent, true, false, false);
11011 if (r_transparentdepthmasking.integer)
11013 qboolean setup = false;
11014 for (i = 0;i < numsurfaces;i = j)
11017 surface = rsurface.modelsurfaces + surfacelist[i];
11018 texture = surface->texture;
11019 rsurface.texture = R_GetCurrentTexture(texture);
11020 rsurface.lightmaptexture = NULL;
11021 rsurface.deluxemaptexture = NULL;
11022 rsurface.uselightmaptexture = false;
11023 // scan ahead until we find a different texture
11024 endsurface = min(i + 1024, numsurfaces);
11025 texturenumsurfaces = 0;
11026 texturesurfacelist[texturenumsurfaces++] = surface;
11027 for (;j < endsurface;j++)
11029 surface = rsurface.modelsurfaces + surfacelist[j];
11030 if (texture != surface->texture)
11032 texturesurfacelist[texturenumsurfaces++] = surface;
11034 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11036 // render the range of surfaces as depth
11040 GL_ColorMask(0,0,0,0);
11042 GL_DepthTest(true);
11043 GL_BlendFunc(GL_ONE, GL_ZERO);
11044 GL_DepthMask(true);
11045 // R_Mesh_ResetTextureState();
11047 RSurf_SetupDepthAndCulling();
11048 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11049 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11050 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11054 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11057 for (i = 0;i < numsurfaces;i = j)
11060 surface = rsurface.modelsurfaces + surfacelist[i];
11061 texture = surface->texture;
11062 rsurface.texture = R_GetCurrentTexture(texture);
11063 // scan ahead until we find a different texture
11064 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11065 texturenumsurfaces = 0;
11066 texturesurfacelist[texturenumsurfaces++] = surface;
11067 if(FAKELIGHT_ENABLED)
11069 rsurface.lightmaptexture = NULL;
11070 rsurface.deluxemaptexture = NULL;
11071 rsurface.uselightmaptexture = false;
11072 for (;j < endsurface;j++)
11074 surface = rsurface.modelsurfaces + surfacelist[j];
11075 if (texture != surface->texture)
11077 texturesurfacelist[texturenumsurfaces++] = surface;
11082 rsurface.lightmaptexture = surface->lightmaptexture;
11083 rsurface.deluxemaptexture = surface->deluxemaptexture;
11084 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11085 for (;j < endsurface;j++)
11087 surface = rsurface.modelsurfaces + surfacelist[j];
11088 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11090 texturesurfacelist[texturenumsurfaces++] = surface;
11093 // render the range of surfaces
11094 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11096 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11099 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11101 // transparent surfaces get pushed off into the transparent queue
11102 int surfacelistindex;
11103 const msurface_t *surface;
11104 vec3_t tempcenter, center;
11105 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11107 surface = texturesurfacelist[surfacelistindex];
11108 if (r_transparent_sortsurfacesbynearest.integer)
11110 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11111 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11112 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11116 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11117 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11118 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11120 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11121 if (rsurface.entity->transparent_offset) // transparent offset
11123 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11124 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11125 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11127 R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11131 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11133 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11135 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11137 RSurf_SetupDepthAndCulling();
11138 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11139 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11140 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11144 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11148 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11151 if (!rsurface.texture->currentnumlayers)
11153 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11154 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11156 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11158 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11159 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11160 else if (!rsurface.texture->currentnumlayers)
11162 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11164 // in the deferred case, transparent surfaces were queued during prepass
11165 if (!r_shadow_usingdeferredprepass)
11166 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11170 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11171 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11176 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11179 texture_t *texture;
11180 R_FrameData_SetMark();
11181 // break the surface list down into batches by texture and use of lightmapping
11182 for (i = 0;i < numsurfaces;i = j)
11185 // texture is the base texture pointer, rsurface.texture is the
11186 // current frame/skin the texture is directing us to use (for example
11187 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11188 // use skin 1 instead)
11189 texture = surfacelist[i]->texture;
11190 rsurface.texture = R_GetCurrentTexture(texture);
11191 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11193 // if this texture is not the kind we want, skip ahead to the next one
11194 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11198 if(FAKELIGHT_ENABLED || depthonly || prepass)
11200 rsurface.lightmaptexture = NULL;
11201 rsurface.deluxemaptexture = NULL;
11202 rsurface.uselightmaptexture = false;
11203 // simply scan ahead until we find a different texture or lightmap state
11204 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11209 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11210 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11211 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11212 // simply scan ahead until we find a different texture or lightmap state
11213 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11216 // render the range of surfaces
11217 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11219 R_FrameData_ReturnToMark();
11222 float locboxvertex3f[6*4*3] =
11224 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11225 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11226 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11227 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11228 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11229 1,0,0, 0,0,0, 0,1,0, 1,1,0
11232 unsigned short locboxelements[6*2*3] =
11237 12,13,14, 12,14,15,
11238 16,17,18, 16,18,19,
11242 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11245 cl_locnode_t *loc = (cl_locnode_t *)ent;
11247 float vertex3f[6*4*3];
11249 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11250 GL_DepthMask(false);
11251 GL_DepthRange(0, 1);
11252 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11253 GL_DepthTest(true);
11254 GL_CullFace(GL_NONE);
11255 R_EntityMatrix(&identitymatrix);
11257 // R_Mesh_ResetTextureState();
11259 i = surfacelist[0];
11260 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11261 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11262 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11263 surfacelist[0] < 0 ? 0.5f : 0.125f);
11265 if (VectorCompare(loc->mins, loc->maxs))
11267 VectorSet(size, 2, 2, 2);
11268 VectorMA(loc->mins, -0.5f, size, mins);
11272 VectorCopy(loc->mins, mins);
11273 VectorSubtract(loc->maxs, loc->mins, size);
11276 for (i = 0;i < 6*4*3;)
11277 for (j = 0;j < 3;j++, i++)
11278 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11280 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11281 R_SetupShader_Generic_NoTexture(false, false);
11282 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11285 void R_DrawLocs(void)
11288 cl_locnode_t *loc, *nearestloc;
11290 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11291 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11293 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11294 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11298 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11300 if (decalsystem->decals)
11301 Mem_Free(decalsystem->decals);
11302 memset(decalsystem, 0, sizeof(*decalsystem));
11305 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, unsigned int decalsequence)
11308 tridecal_t *decals;
11311 // expand or initialize the system
11312 if (decalsystem->maxdecals <= decalsystem->numdecals)
11314 decalsystem_t old = *decalsystem;
11315 qboolean useshortelements;
11316 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11317 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11318 decalsystem->decals = (tridecal_t *)Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
11319 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11320 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11321 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11322 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11323 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11324 if (decalsystem->numdecals)
11325 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11327 Mem_Free(old.decals);
11328 for (i = 0;i < decalsystem->maxdecals*3;i++)
11329 decalsystem->element3i[i] = i;
11330 if (useshortelements)
11331 for (i = 0;i < decalsystem->maxdecals*3;i++)
11332 decalsystem->element3s[i] = i;
11335 // grab a decal and search for another free slot for the next one
11336 decals = decalsystem->decals;
11337 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11338 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11340 decalsystem->freedecal = i;
11341 if (decalsystem->numdecals <= i)
11342 decalsystem->numdecals = i + 1;
11344 // initialize the decal
11346 decal->triangleindex = triangleindex;
11347 decal->surfaceindex = surfaceindex;
11348 decal->decalsequence = decalsequence;
11349 decal->color4f[0][0] = c0[0];
11350 decal->color4f[0][1] = c0[1];
11351 decal->color4f[0][2] = c0[2];
11352 decal->color4f[0][3] = 1;
11353 decal->color4f[1][0] = c1[0];
11354 decal->color4f[1][1] = c1[1];
11355 decal->color4f[1][2] = c1[2];
11356 decal->color4f[1][3] = 1;
11357 decal->color4f[2][0] = c2[0];
11358 decal->color4f[2][1] = c2[1];
11359 decal->color4f[2][2] = c2[2];
11360 decal->color4f[2][3] = 1;
11361 decal->vertex3f[0][0] = v0[0];
11362 decal->vertex3f[0][1] = v0[1];
11363 decal->vertex3f[0][2] = v0[2];
11364 decal->vertex3f[1][0] = v1[0];
11365 decal->vertex3f[1][1] = v1[1];
11366 decal->vertex3f[1][2] = v1[2];
11367 decal->vertex3f[2][0] = v2[0];
11368 decal->vertex3f[2][1] = v2[1];
11369 decal->vertex3f[2][2] = v2[2];
11370 decal->texcoord2f[0][0] = t0[0];
11371 decal->texcoord2f[0][1] = t0[1];
11372 decal->texcoord2f[1][0] = t1[0];
11373 decal->texcoord2f[1][1] = t1[1];
11374 decal->texcoord2f[2][0] = t2[0];
11375 decal->texcoord2f[2][1] = t2[1];
11376 TriangleNormal(v0, v1, v2, decal->plane);
11377 VectorNormalize(decal->plane);
11378 decal->plane[3] = DotProduct(v0, decal->plane);
11381 extern cvar_t cl_decals_bias;
11382 extern cvar_t cl_decals_models;
11383 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11384 // baseparms, parms, temps
11385 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11390 const float *vertex3f;
11391 const float *normal3f;
11393 float points[2][9][3];
11400 e = rsurface.modelelement3i + 3*triangleindex;
11402 vertex3f = rsurface.modelvertex3f;
11403 normal3f = rsurface.modelnormal3f;
11407 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11409 index = 3*e[cornerindex];
11410 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11415 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11417 index = 3*e[cornerindex];
11418 VectorCopy(vertex3f + index, v[cornerindex]);
11423 //TriangleNormal(v[0], v[1], v[2], normal);
11424 //if (DotProduct(normal, localnormal) < 0.0f)
11426 // clip by each of the box planes formed from the projection matrix
11427 // if anything survives, we emit the decal
11428 numpoints = PolygonF_Clip(3 , v[0] , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11431 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
11434 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11437 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
11440 numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11443 numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
11446 // some part of the triangle survived, so we have to accept it...
11449 // dynamic always uses the original triangle
11451 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11453 index = 3*e[cornerindex];
11454 VectorCopy(vertex3f + index, v[cornerindex]);
11457 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11459 // convert vertex positions to texcoords
11460 Matrix4x4_Transform(projection, v[cornerindex], temp);
11461 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11462 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11463 // calculate distance fade from the projection origin
11464 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11465 f = bound(0.0f, f, 1.0f);
11466 c[cornerindex][0] = r * f;
11467 c[cornerindex][1] = g * f;
11468 c[cornerindex][2] = b * f;
11469 c[cornerindex][3] = 1.0f;
11470 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11473 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
11475 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11476 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
11478 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, unsigned int decalsequence)
11480 matrix4x4_t projection;
11481 decalsystem_t *decalsystem;
11484 const msurface_t *surface;
11485 const msurface_t *surfaces;
11486 const int *surfacelist;
11487 const texture_t *texture;
11489 int numsurfacelist;
11490 int surfacelistindex;
11493 float localorigin[3];
11494 float localnormal[3];
11495 float localmins[3];
11496 float localmaxs[3];
11499 float planes[6][4];
11502 int bih_triangles_count;
11503 int bih_triangles[256];
11504 int bih_surfaces[256];
11506 decalsystem = &ent->decalsystem;
11507 model = ent->model;
11508 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11510 R_DecalSystem_Reset(&ent->decalsystem);
11514 if (!model->brush.data_leafs && !cl_decals_models.integer)
11516 if (decalsystem->model)
11517 R_DecalSystem_Reset(decalsystem);
11521 if (decalsystem->model != model)
11522 R_DecalSystem_Reset(decalsystem);
11523 decalsystem->model = model;
11525 RSurf_ActiveModelEntity(ent, true, false, false);
11527 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11528 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11529 VectorNormalize(localnormal);
11530 localsize = worldsize*rsurface.inversematrixscale;
11531 localmins[0] = localorigin[0] - localsize;
11532 localmins[1] = localorigin[1] - localsize;
11533 localmins[2] = localorigin[2] - localsize;
11534 localmaxs[0] = localorigin[0] + localsize;
11535 localmaxs[1] = localorigin[1] + localsize;
11536 localmaxs[2] = localorigin[2] + localsize;
11538 //VectorCopy(localnormal, planes[4]);
11539 //VectorVectors(planes[4], planes[2], planes[0]);
11540 AnglesFromVectors(angles, localnormal, NULL, false);
11541 AngleVectors(angles, planes[0], planes[2], planes[4]);
11542 VectorNegate(planes[0], planes[1]);
11543 VectorNegate(planes[2], planes[3]);
11544 VectorNegate(planes[4], planes[5]);
11545 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11546 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11547 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11548 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11549 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11550 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11555 matrix4x4_t forwardprojection;
11556 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11557 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11562 float projectionvector[4][3];
11563 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11564 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11565 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11566 projectionvector[0][0] = planes[0][0] * ilocalsize;
11567 projectionvector[0][1] = planes[1][0] * ilocalsize;
11568 projectionvector[0][2] = planes[2][0] * ilocalsize;
11569 projectionvector[1][0] = planes[0][1] * ilocalsize;
11570 projectionvector[1][1] = planes[1][1] * ilocalsize;
11571 projectionvector[1][2] = planes[2][1] * ilocalsize;
11572 projectionvector[2][0] = planes[0][2] * ilocalsize;
11573 projectionvector[2][1] = planes[1][2] * ilocalsize;
11574 projectionvector[2][2] = planes[2][2] * ilocalsize;
11575 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11576 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11577 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11578 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11582 dynamic = model->surfmesh.isanimated;
11583 numsurfacelist = model->nummodelsurfaces;
11584 surfacelist = model->sortedmodelsurfaces;
11585 surfaces = model->data_surfaces;
11588 bih_triangles_count = -1;
11591 if(model->render_bih.numleafs)
11592 bih = &model->render_bih;
11593 else if(model->collision_bih.numleafs)
11594 bih = &model->collision_bih;
11597 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11598 if(bih_triangles_count == 0)
11600 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11602 if(bih_triangles_count > 0)
11604 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11606 surfaceindex = bih_surfaces[triangleindex];
11607 surface = surfaces + surfaceindex;
11608 texture = surface->texture;
11609 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11611 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11613 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11618 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11620 surfaceindex = surfacelist[surfacelistindex];
11621 surface = surfaces + surfaceindex;
11622 // check cull box first because it rejects more than any other check
11623 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11625 // skip transparent surfaces
11626 texture = surface->texture;
11627 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11629 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11631 numtriangles = surface->num_triangles;
11632 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11633 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11638 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11639 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, unsigned int decalsequence)
11641 int renderentityindex;
11642 float worldmins[3];
11643 float worldmaxs[3];
11644 entity_render_t *ent;
11646 if (!cl_decals_newsystem.integer)
11649 worldmins[0] = worldorigin[0] - worldsize;
11650 worldmins[1] = worldorigin[1] - worldsize;
11651 worldmins[2] = worldorigin[2] - worldsize;
11652 worldmaxs[0] = worldorigin[0] + worldsize;
11653 worldmaxs[1] = worldorigin[1] + worldsize;
11654 worldmaxs[2] = worldorigin[2] + worldsize;
11656 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11658 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11660 ent = r_refdef.scene.entities[renderentityindex];
11661 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11664 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11668 typedef struct r_decalsystem_splatqueue_s
11670 vec3_t worldorigin;
11671 vec3_t worldnormal;
11675 unsigned int decalsequence;
11677 r_decalsystem_splatqueue_t;
11679 int r_decalsystem_numqueued = 0;
11680 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11682 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
11684 r_decalsystem_splatqueue_t *queue;
11686 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11689 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11690 VectorCopy(worldorigin, queue->worldorigin);
11691 VectorCopy(worldnormal, queue->worldnormal);
11692 Vector4Set(queue->color, r, g, b, a);
11693 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11694 queue->worldsize = worldsize;
11695 queue->decalsequence = cl.decalsequence++;
11698 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11701 r_decalsystem_splatqueue_t *queue;
11703 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11704 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
11705 r_decalsystem_numqueued = 0;
11708 extern cvar_t cl_decals_max;
11709 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11712 decalsystem_t *decalsystem = &ent->decalsystem;
11714 unsigned int killsequence;
11719 if (!decalsystem->numdecals)
11722 if (r_showsurfaces.integer)
11725 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11727 R_DecalSystem_Reset(decalsystem);
11731 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11732 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11734 if (decalsystem->lastupdatetime)
11735 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11738 decalsystem->lastupdatetime = r_refdef.scene.time;
11739 numdecals = decalsystem->numdecals;
11741 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11743 if (decal->color4f[0][3])
11745 decal->lived += frametime;
11746 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11748 memset(decal, 0, sizeof(*decal));
11749 if (decalsystem->freedecal > i)
11750 decalsystem->freedecal = i;
11754 decal = decalsystem->decals;
11755 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11758 // collapse the array by shuffling the tail decals into the gaps
11761 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11762 decalsystem->freedecal++;
11763 if (decalsystem->freedecal == numdecals)
11765 decal[decalsystem->freedecal] = decal[--numdecals];
11768 decalsystem->numdecals = numdecals;
11770 if (numdecals <= 0)
11772 // if there are no decals left, reset decalsystem
11773 R_DecalSystem_Reset(decalsystem);
11777 extern skinframe_t *decalskinframe;
11778 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11781 decalsystem_t *decalsystem = &ent->decalsystem;
11790 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11793 numdecals = decalsystem->numdecals;
11797 if (r_showsurfaces.integer)
11800 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11802 R_DecalSystem_Reset(decalsystem);
11806 // if the model is static it doesn't matter what value we give for
11807 // wantnormals and wanttangents, so this logic uses only rules applicable
11808 // to a model, knowing that they are meaningless otherwise
11809 RSurf_ActiveModelEntity(ent, false, false, false);
11811 decalsystem->lastupdatetime = r_refdef.scene.time;
11813 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11815 // update vertex positions for animated models
11816 v3f = decalsystem->vertex3f;
11817 c4f = decalsystem->color4f;
11818 t2f = decalsystem->texcoord2f;
11819 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11821 if (!decal->color4f[0][3])
11824 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11828 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11831 // update color values for fading decals
11832 if (decal->lived >= cl_decals_time.value)
11833 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11837 c4f[ 0] = decal->color4f[0][0] * alpha;
11838 c4f[ 1] = decal->color4f[0][1] * alpha;
11839 c4f[ 2] = decal->color4f[0][2] * alpha;
11841 c4f[ 4] = decal->color4f[1][0] * alpha;
11842 c4f[ 5] = decal->color4f[1][1] * alpha;
11843 c4f[ 6] = decal->color4f[1][2] * alpha;
11845 c4f[ 8] = decal->color4f[2][0] * alpha;
11846 c4f[ 9] = decal->color4f[2][1] * alpha;
11847 c4f[10] = decal->color4f[2][2] * alpha;
11850 t2f[0] = decal->texcoord2f[0][0];
11851 t2f[1] = decal->texcoord2f[0][1];
11852 t2f[2] = decal->texcoord2f[1][0];
11853 t2f[3] = decal->texcoord2f[1][1];
11854 t2f[4] = decal->texcoord2f[2][0];
11855 t2f[5] = decal->texcoord2f[2][1];
11857 // update vertex positions for animated models
11858 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11860 e = rsurface.modelelement3i + 3*decal->triangleindex;
11861 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11862 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11863 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11867 VectorCopy(decal->vertex3f[0], v3f);
11868 VectorCopy(decal->vertex3f[1], v3f + 3);
11869 VectorCopy(decal->vertex3f[2], v3f + 6);
11872 if (r_refdef.fogenabled)
11874 alpha = RSurf_FogVertex(v3f);
11875 VectorScale(c4f, alpha, c4f);
11876 alpha = RSurf_FogVertex(v3f + 3);
11877 VectorScale(c4f + 4, alpha, c4f + 4);
11878 alpha = RSurf_FogVertex(v3f + 6);
11879 VectorScale(c4f + 8, alpha, c4f + 8);
11890 r_refdef.stats[r_stat_drawndecals] += numtris;
11892 // now render the decals all at once
11893 // (this assumes they all use one particle font texture!)
11894 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11895 // R_Mesh_ResetTextureState();
11896 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11897 GL_DepthMask(false);
11898 GL_DepthRange(0, 1);
11899 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11900 GL_DepthTest(true);
11901 GL_CullFace(GL_NONE);
11902 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11903 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11904 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11908 static void R_DrawModelDecals(void)
11912 // fade faster when there are too many decals
11913 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11914 for (i = 0;i < r_refdef.scene.numentities;i++)
11915 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11917 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11918 for (i = 0;i < r_refdef.scene.numentities;i++)
11919 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11920 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11922 R_DecalSystem_ApplySplatEntitiesQueue();
11924 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11925 for (i = 0;i < r_refdef.scene.numentities;i++)
11926 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11928 r_refdef.stats[r_stat_totaldecals] += numdecals;
11930 if (r_showsurfaces.integer)
11933 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11935 for (i = 0;i < r_refdef.scene.numentities;i++)
11937 if (!r_refdef.viewcache.entityvisible[i])
11939 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11940 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11944 extern cvar_t mod_collision_bih;
11945 static void R_DrawDebugModel(void)
11947 entity_render_t *ent = rsurface.entity;
11948 int i, j, flagsmask;
11949 const msurface_t *surface;
11950 dp_model_t *model = ent->model;
11952 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11955 if (r_showoverdraw.value > 0)
11957 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11958 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11959 R_SetupShader_Generic_NoTexture(false, false);
11960 GL_DepthTest(false);
11961 GL_DepthMask(false);
11962 GL_DepthRange(0, 1);
11963 GL_BlendFunc(GL_ONE, GL_ONE);
11964 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11966 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11968 rsurface.texture = R_GetCurrentTexture(surface->texture);
11969 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11971 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11972 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11973 if (!rsurface.texture->currentlayers->depthmask)
11974 GL_Color(c, 0, 0, 1.0f);
11975 else if (ent == r_refdef.scene.worldentity)
11976 GL_Color(c, c, c, 1.0f);
11978 GL_Color(0, c, 0, 1.0f);
11979 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11983 rsurface.texture = NULL;
11986 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11988 // R_Mesh_ResetTextureState();
11989 R_SetupShader_Generic_NoTexture(false, false);
11990 GL_DepthRange(0, 1);
11991 GL_DepthTest(!r_showdisabledepthtest.integer);
11992 GL_DepthMask(false);
11993 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11995 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11999 qboolean cullbox = false;
12000 const q3mbrush_t *brush;
12001 const bih_t *bih = &model->collision_bih;
12002 const bih_leaf_t *bihleaf;
12003 float vertex3f[3][3];
12004 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12005 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12007 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12009 switch (bihleaf->type)
12012 brush = model->brush.data_brushes + bihleaf->itemindex;
12013 if (brush->colbrushf && brush->colbrushf->numtriangles)
12015 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12016 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12017 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12020 case BIH_COLLISIONTRIANGLE:
12021 triangleindex = bihleaf->itemindex;
12022 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12023 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12024 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12025 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12026 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12027 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12029 case BIH_RENDERTRIANGLE:
12030 triangleindex = bihleaf->itemindex;
12031 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12032 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12033 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12034 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12035 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12036 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12042 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12045 if (r_showtris.integer && qglPolygonMode)
12047 if (r_showdisabledepthtest.integer)
12049 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12050 GL_DepthMask(false);
12054 GL_BlendFunc(GL_ONE, GL_ZERO);
12055 GL_DepthMask(true);
12057 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12058 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12060 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12062 rsurface.texture = R_GetCurrentTexture(surface->texture);
12063 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12065 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12066 if (!rsurface.texture->currentlayers->depthmask)
12067 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12068 else if (ent == r_refdef.scene.worldentity)
12069 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12071 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12072 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12076 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12077 rsurface.texture = NULL;
12080 if (r_shownormals.value != 0 && qglBegin)
12084 if (r_showdisabledepthtest.integer)
12086 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12087 GL_DepthMask(false);
12091 GL_BlendFunc(GL_ONE, GL_ZERO);
12092 GL_DepthMask(true);
12094 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12096 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12098 rsurface.texture = R_GetCurrentTexture(surface->texture);
12099 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12101 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12102 qglBegin(GL_LINES);
12103 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12105 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12107 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12108 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12109 qglVertex3f(v[0], v[1], v[2]);
12110 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12111 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12112 qglVertex3f(v[0], v[1], v[2]);
12115 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12117 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12119 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12120 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12121 qglVertex3f(v[0], v[1], v[2]);
12122 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12123 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12124 qglVertex3f(v[0], v[1], v[2]);
12127 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12129 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12131 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12132 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12133 qglVertex3f(v[0], v[1], v[2]);
12134 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12135 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12136 qglVertex3f(v[0], v[1], v[2]);
12139 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12141 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12143 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12144 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12145 qglVertex3f(v[0], v[1], v[2]);
12146 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12147 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12148 qglVertex3f(v[0], v[1], v[2]);
12155 rsurface.texture = NULL;
12160 int r_maxsurfacelist = 0;
12161 const msurface_t **r_surfacelist = NULL;
12162 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12164 int i, j, endj, flagsmask;
12165 dp_model_t *model = ent->model;
12166 msurface_t *surfaces;
12167 unsigned char *update;
12168 int numsurfacelist = 0;
12172 if (r_maxsurfacelist < model->num_surfaces)
12174 r_maxsurfacelist = model->num_surfaces;
12176 Mem_Free((msurface_t **)r_surfacelist);
12177 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12180 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12181 RSurf_ActiveModelEntity(ent, false, false, false);
12183 RSurf_ActiveModelEntity(ent, true, true, true);
12184 else if (depthonly)
12186 switch (vid.renderpath)
12188 case RENDERPATH_GL20:
12189 case RENDERPATH_D3D9:
12190 case RENDERPATH_D3D10:
12191 case RENDERPATH_D3D11:
12192 case RENDERPATH_SOFT:
12193 case RENDERPATH_GLES2:
12194 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12196 case RENDERPATH_GL11:
12197 case RENDERPATH_GL13:
12198 case RENDERPATH_GLES1:
12199 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12205 switch (vid.renderpath)
12207 case RENDERPATH_GL20:
12208 case RENDERPATH_D3D9:
12209 case RENDERPATH_D3D10:
12210 case RENDERPATH_D3D11:
12211 case RENDERPATH_SOFT:
12212 case RENDERPATH_GLES2:
12213 RSurf_ActiveModelEntity(ent, true, true, false);
12215 case RENDERPATH_GL11:
12216 case RENDERPATH_GL13:
12217 case RENDERPATH_GLES1:
12218 RSurf_ActiveModelEntity(ent, true, false, false);
12223 surfaces = model->data_surfaces;
12224 update = model->brushq1.lightmapupdateflags;
12226 // update light styles
12227 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12229 model_brush_lightstyleinfo_t *style;
12230 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12232 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12234 int *list = style->surfacelist;
12235 style->value = r_refdef.scene.lightstylevalue[style->style];
12236 for (j = 0;j < style->numsurfaces;j++)
12237 update[list[j]] = true;
12242 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12246 R_DrawDebugModel();
12247 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12251 rsurface.lightmaptexture = NULL;
12252 rsurface.deluxemaptexture = NULL;
12253 rsurface.uselightmaptexture = false;
12254 rsurface.texture = NULL;
12255 rsurface.rtlight = NULL;
12256 numsurfacelist = 0;
12257 // add visible surfaces to draw list
12258 if (ent == r_refdef.scene.worldentity)
12260 // for the world entity, check surfacevisible
12261 for (i = 0;i < model->nummodelsurfaces;i++)
12263 j = model->sortedmodelsurfaces[i];
12264 if (r_refdef.viewcache.world_surfacevisible[j])
12265 r_surfacelist[numsurfacelist++] = surfaces + j;
12270 // add all surfaces
12271 for (i = 0; i < model->nummodelsurfaces; i++)
12272 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12274 // don't do anything if there were no surfaces
12275 if (!numsurfacelist)
12277 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12280 // update lightmaps if needed
12284 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12289 R_BuildLightMap(ent, surfaces + j);
12294 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12296 // add to stats if desired
12297 if (r_speeds.integer && !skysurfaces && !depthonly)
12299 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12300 for (j = 0;j < numsurfacelist;j++)
12301 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12304 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12307 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12310 static texture_t texture;
12311 static msurface_t surface;
12312 const msurface_t *surfacelist = &surface;
12314 // fake enough texture and surface state to render this geometry
12316 texture.update_lastrenderframe = -1; // regenerate this texture
12317 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12318 texture.basealpha = 1.0f;
12319 texture.currentskinframe = skinframe;
12320 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12321 texture.offsetmapping = OFFSETMAPPING_OFF;
12322 texture.offsetscale = 1;
12323 texture.specularscalemod = 1;
12324 texture.specularpowermod = 1;
12325 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12326 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12327 // JUST GREP FOR "specularscalemod = 1".
12329 for (q = 0; q < 3; q++)
12331 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12332 texture.render_modellight_lightdir[q] = q == 2;
12333 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12334 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12335 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12336 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12337 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12338 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12339 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12340 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12342 texture.currentalpha = 1.0f;
12344 surface.texture = &texture;
12345 surface.num_triangles = numtriangles;
12346 surface.num_firsttriangle = firsttriangle;
12347 surface.num_vertices = numvertices;
12348 surface.num_firstvertex = firstvertex;
12351 rsurface.texture = R_GetCurrentTexture(surface.texture);
12352 rsurface.lightmaptexture = NULL;
12353 rsurface.deluxemaptexture = NULL;
12354 rsurface.uselightmaptexture = false;
12355 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12358 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12360 static msurface_t surface;
12361 const msurface_t *surfacelist = &surface;
12363 // fake enough texture and surface state to render this geometry
12364 surface.texture = texture;
12365 surface.num_triangles = numtriangles;
12366 surface.num_firsttriangle = firsttriangle;
12367 surface.num_vertices = numvertices;
12368 surface.num_firstvertex = firstvertex;
12371 rsurface.texture = R_GetCurrentTexture(surface.texture);
12372 rsurface.lightmaptexture = NULL;
12373 rsurface.deluxemaptexture = NULL;
12374 rsurface.uselightmaptexture = false;
12375 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);