2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.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"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
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)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
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_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)"};
97 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
98 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
99 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"};
100 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"};
101 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
102 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"};
103 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"};
104 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"};
105 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
106 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
107 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
108 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
109 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
110 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
111 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
112 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)"};
113 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)"};
114 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
115 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
116 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
117 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
118 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
120 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
121 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
122 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
124 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
125 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
126 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
127 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."};
128 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
129 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
130 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
131 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."};
132 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
133 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
134 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
135 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."};
136 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
137 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"};
138 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"};
139 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
140 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
141 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
142 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
143 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
144 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"};
145 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
146 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
147 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
148 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
149 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
151 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
152 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
153 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
154 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
155 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
156 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
157 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
158 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
160 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)"};
161 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"};
163 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
164 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
165 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
167 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"};
168 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"};
169 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"};
170 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
171 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
172 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"};
173 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)"};
174 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)"};
175 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
177 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
178 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)"};
179 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
180 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)"};
181 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
182 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)"};
183 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)"};
184 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
185 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"};
186 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."};
187 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
188 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)"};
189 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)"};
190 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)"};
191 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)"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
197 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)"};
198 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)"};
199 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
200 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"};
201 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
202 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
203 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
204 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"};
205 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"};
206 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
208 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
209 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
210 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
211 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
213 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
214 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
216 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
217 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
218 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
219 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
220 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
221 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
223 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
224 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
225 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
226 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
227 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
228 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
229 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
230 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
231 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
232 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
234 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"};
236 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"};
238 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
240 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
242 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)"};
243 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)"};
244 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
245 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
247 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
248 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"};
250 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."};
252 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)"};
253 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
255 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
256 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
257 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
258 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
261 extern cvar_t v_glslgamma;
262 extern cvar_t v_glslgamma_2d;
264 extern qboolean v_flipped_state;
266 r_framebufferstate_t r_fb;
268 /// shadow volume bsp struct with automatically growing nodes buffer
271 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
273 rtexture_t *r_texture_blanknormalmap;
274 rtexture_t *r_texture_white;
275 rtexture_t *r_texture_grey128;
276 rtexture_t *r_texture_black;
277 rtexture_t *r_texture_notexture;
278 rtexture_t *r_texture_whitecube;
279 rtexture_t *r_texture_normalizationcube;
280 rtexture_t *r_texture_fogattenuation;
281 rtexture_t *r_texture_fogheighttexture;
282 rtexture_t *r_texture_gammaramps;
283 unsigned int r_texture_gammaramps_serial;
284 //rtexture_t *r_texture_fogintensity;
285 rtexture_t *r_texture_reflectcube;
287 // TODO: hash lookups?
288 typedef struct cubemapinfo_s
295 int r_texture_numcubemaps;
296 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
298 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
299 unsigned int r_numqueries;
300 unsigned int r_maxqueries;
302 typedef struct r_qwskincache_s
304 char name[MAX_QPATH];
305 skinframe_t *skinframe;
309 static r_qwskincache_t *r_qwskincache;
310 static int r_qwskincache_size;
312 /// vertex coordinates for a quad that covers the screen exactly
313 extern const float r_screenvertex3f[12];
314 extern const float r_d3dscreenvertex3f[12];
315 const float r_screenvertex3f[12] =
322 const float r_d3dscreenvertex3f[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 unsigned int 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, unsigned int 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, unsigned int 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, unsigned int 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";
1119 // the first pretext is which type of shader to compile as
1120 // (later these will all be bound together as a program object)
1121 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1122 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1123 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1125 // the second pretext is the mode (for example a light source)
1126 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1127 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1128 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1129 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1131 // now add all the permutation pretexts
1132 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1134 if (permutation & (1<<i))
1136 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1137 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1138 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1139 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1143 // keep line numbers correct
1144 vertstrings_list[vertstrings_count++] = "\n";
1145 geomstrings_list[geomstrings_count++] = "\n";
1146 fragstrings_list[fragstrings_count++] = "\n";
1151 R_CompileShader_AddStaticParms(mode, permutation);
1152 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1153 vertstrings_count += shaderstaticparms_count;
1154 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1155 geomstrings_count += shaderstaticparms_count;
1156 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1157 fragstrings_count += shaderstaticparms_count;
1159 // now append the shader text itself
1160 vertstrings_list[vertstrings_count++] = sourcestring;
1161 geomstrings_list[geomstrings_count++] = sourcestring;
1162 fragstrings_list[fragstrings_count++] = sourcestring;
1164 // compile the shader program
1165 if (vertstrings_count + geomstrings_count + fragstrings_count)
1166 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1170 qglUseProgram(p->program);CHECKGLERROR
1171 // look up all the uniform variable names we care about, so we don't
1172 // have to look them up every time we set them
1177 GLint activeuniformindex = 0;
1178 GLint numactiveuniforms = 0;
1179 char uniformname[128];
1180 GLsizei uniformnamelength = 0;
1181 GLint uniformsize = 0;
1182 GLenum uniformtype = 0;
1183 memset(uniformname, 0, sizeof(uniformname));
1184 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1185 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1186 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1188 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1189 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1194 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1195 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1196 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1197 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1198 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1199 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1200 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1201 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1202 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1203 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1204 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1205 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1206 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1207 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1208 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1209 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1210 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1211 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1212 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1213 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1214 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1215 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1216 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1217 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1218 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1219 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1220 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1221 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1222 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1223 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1224 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1225 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1226 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1227 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1228 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1229 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1230 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1231 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1232 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1233 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1234 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1235 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1236 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1237 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1238 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1239 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1240 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1241 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1242 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1243 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1244 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1245 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1246 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1247 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1248 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1249 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1250 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1251 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1252 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1253 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1254 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1255 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1256 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1257 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1258 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1259 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1260 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1261 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1262 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1263 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1264 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1265 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1266 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1267 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1268 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1269 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1270 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1271 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1272 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1273 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1274 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1275 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1276 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1277 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1278 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1279 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1280 // initialize the samplers to refer to the texture units we use
1281 p->tex_Texture_First = -1;
1282 p->tex_Texture_Second = -1;
1283 p->tex_Texture_GammaRamps = -1;
1284 p->tex_Texture_Normal = -1;
1285 p->tex_Texture_Color = -1;
1286 p->tex_Texture_Gloss = -1;
1287 p->tex_Texture_Glow = -1;
1288 p->tex_Texture_SecondaryNormal = -1;
1289 p->tex_Texture_SecondaryColor = -1;
1290 p->tex_Texture_SecondaryGloss = -1;
1291 p->tex_Texture_SecondaryGlow = -1;
1292 p->tex_Texture_Pants = -1;
1293 p->tex_Texture_Shirt = -1;
1294 p->tex_Texture_FogHeightTexture = -1;
1295 p->tex_Texture_FogMask = -1;
1296 p->tex_Texture_Lightmap = -1;
1297 p->tex_Texture_Deluxemap = -1;
1298 p->tex_Texture_Attenuation = -1;
1299 p->tex_Texture_Cube = -1;
1300 p->tex_Texture_Refraction = -1;
1301 p->tex_Texture_Reflection = -1;
1302 p->tex_Texture_ShadowMap2D = -1;
1303 p->tex_Texture_CubeProjection = -1;
1304 p->tex_Texture_ScreenNormalMap = -1;
1305 p->tex_Texture_ScreenDiffuse = -1;
1306 p->tex_Texture_ScreenSpecular = -1;
1307 p->tex_Texture_ReflectMask = -1;
1308 p->tex_Texture_ReflectCube = -1;
1309 p->tex_Texture_BounceGrid = -1;
1310 // bind the texture samplers in use
1312 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1313 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1314 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1315 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1316 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1317 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1318 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1319 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1320 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1321 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1322 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1323 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1324 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1325 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1326 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1327 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1328 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1329 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1330 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1331 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1332 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1333 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1334 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1335 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1336 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1337 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1338 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1339 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1340 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1341 // get the uniform block indices so we can bind them
1342 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1343 if (vid.support.arb_uniform_buffer_object)
1344 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1347 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1348 // clear the uniform block bindings
1349 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1350 // bind the uniform blocks in use
1352 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1353 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1355 // we're done compiling and setting up the shader, at least until it is used
1357 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1360 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1364 Mem_Free(sourcestring);
1367 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1369 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1370 if (r_glsl_permutation != perm)
1372 r_glsl_permutation = perm;
1373 if (!r_glsl_permutation->program)
1375 if (!r_glsl_permutation->compiled)
1377 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1378 R_GLSL_CompilePermutation(perm, mode, permutation);
1380 if (!r_glsl_permutation->program)
1382 // remove features until we find a valid permutation
1384 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1386 // reduce i more quickly whenever it would not remove any bits
1387 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1388 if (!(permutation & j))
1391 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1392 if (!r_glsl_permutation->compiled)
1393 R_GLSL_CompilePermutation(perm, mode, permutation);
1394 if (r_glsl_permutation->program)
1397 if (i >= SHADERPERMUTATION_COUNT)
1399 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1400 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1401 qglUseProgram(0);CHECKGLERROR
1402 return; // no bit left to clear, entire mode is broken
1407 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1409 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1410 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1411 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1419 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1420 extern D3DCAPS9 vid_d3d9caps;
1423 struct r_hlsl_permutation_s;
1424 typedef struct r_hlsl_permutation_s
1426 /// hash lookup data
1427 struct r_hlsl_permutation_s *hashnext;
1429 unsigned int permutation;
1431 /// indicates if we have tried compiling this permutation already
1433 /// NULL if compilation failed
1434 IDirect3DVertexShader9 *vertexshader;
1435 IDirect3DPixelShader9 *pixelshader;
1437 r_hlsl_permutation_t;
1439 typedef enum D3DVSREGISTER_e
1441 D3DVSREGISTER_TexMatrix = 0, // float4x4
1442 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1443 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1444 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1445 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1446 D3DVSREGISTER_ModelToLight = 20, // float4x4
1447 D3DVSREGISTER_EyePosition = 24,
1448 D3DVSREGISTER_FogPlane = 25,
1449 D3DVSREGISTER_LightDir = 26,
1450 D3DVSREGISTER_LightPosition = 27,
1454 typedef enum D3DPSREGISTER_e
1456 D3DPSREGISTER_Alpha = 0,
1457 D3DPSREGISTER_BloomBlur_Parameters = 1,
1458 D3DPSREGISTER_ClientTime = 2,
1459 D3DPSREGISTER_Color_Ambient = 3,
1460 D3DPSREGISTER_Color_Diffuse = 4,
1461 D3DPSREGISTER_Color_Specular = 5,
1462 D3DPSREGISTER_Color_Glow = 6,
1463 D3DPSREGISTER_Color_Pants = 7,
1464 D3DPSREGISTER_Color_Shirt = 8,
1465 D3DPSREGISTER_DeferredColor_Ambient = 9,
1466 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1467 D3DPSREGISTER_DeferredColor_Specular = 11,
1468 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1469 D3DPSREGISTER_DeferredMod_Specular = 13,
1470 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1471 D3DPSREGISTER_EyePosition = 15, // unused
1472 D3DPSREGISTER_FogColor = 16,
1473 D3DPSREGISTER_FogHeightFade = 17,
1474 D3DPSREGISTER_FogPlane = 18,
1475 D3DPSREGISTER_FogPlaneViewDist = 19,
1476 D3DPSREGISTER_FogRangeRecip = 20,
1477 D3DPSREGISTER_LightColor = 21,
1478 D3DPSREGISTER_LightDir = 22, // unused
1479 D3DPSREGISTER_LightPosition = 23,
1480 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1481 D3DPSREGISTER_PixelSize = 25,
1482 D3DPSREGISTER_ReflectColor = 26,
1483 D3DPSREGISTER_ReflectFactor = 27,
1484 D3DPSREGISTER_ReflectOffset = 28,
1485 D3DPSREGISTER_RefractColor = 29,
1486 D3DPSREGISTER_Saturation = 30,
1487 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1488 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1489 D3DPSREGISTER_ScreenToDepth = 33,
1490 D3DPSREGISTER_ShadowMap_Parameters = 34,
1491 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1492 D3DPSREGISTER_SpecularPower = 36,
1493 D3DPSREGISTER_UserVec1 = 37,
1494 D3DPSREGISTER_UserVec2 = 38,
1495 D3DPSREGISTER_UserVec3 = 39,
1496 D3DPSREGISTER_UserVec4 = 40,
1497 D3DPSREGISTER_ViewTintColor = 41,
1498 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1499 D3DPSREGISTER_BloomColorSubtract = 43,
1500 D3DPSREGISTER_ViewToLight = 44, // float4x4
1501 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1502 D3DPSREGISTER_NormalmapScrollBlend = 52,
1503 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1504 D3DPSREGISTER_OffsetMapping_Bias = 54,
1509 /// information about each possible shader permutation
1510 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1511 /// currently selected permutation
1512 r_hlsl_permutation_t *r_hlsl_permutation;
1513 /// storage for permutations linked in the hash table
1514 memexpandablearray_t r_hlsl_permutationarray;
1516 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1518 //unsigned int hashdepth = 0;
1519 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1520 r_hlsl_permutation_t *p;
1521 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1523 if (p->mode == mode && p->permutation == permutation)
1525 //if (hashdepth > 10)
1526 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1531 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1533 p->permutation = permutation;
1534 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1535 r_hlsl_permutationhash[mode][hashindex] = p;
1536 //if (hashdepth > 10)
1537 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1542 //#include <d3dx9shader.h>
1543 //#include <d3dx9mesh.h>
1545 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1547 DWORD *vsbin = NULL;
1548 DWORD *psbin = NULL;
1549 fs_offset_t vsbinsize;
1550 fs_offset_t psbinsize;
1551 // IDirect3DVertexShader9 *vs = NULL;
1552 // IDirect3DPixelShader9 *ps = NULL;
1553 ID3DXBuffer *vslog = NULL;
1554 ID3DXBuffer *vsbuffer = NULL;
1555 ID3DXConstantTable *vsconstanttable = NULL;
1556 ID3DXBuffer *pslog = NULL;
1557 ID3DXBuffer *psbuffer = NULL;
1558 ID3DXConstantTable *psconstanttable = NULL;
1561 char temp[MAX_INPUTLINE];
1562 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1564 qboolean debugshader = gl_paranoid.integer != 0;
1565 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1566 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1569 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1570 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1572 if ((!vsbin && vertstring) || (!psbin && fragstring))
1574 const char* dllnames_d3dx9 [] =
1598 dllhandle_t d3dx9_dll = NULL;
1599 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1600 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1601 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1602 dllfunction_t d3dx9_dllfuncs[] =
1604 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1605 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1606 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1609 // 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...
1610 #ifndef ID3DXBuffer_GetBufferPointer
1611 #if !defined(__cplusplus) || defined(CINTERFACE)
1612 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1613 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1614 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1616 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1617 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1618 #define ID3DXBuffer_Release(p) (p)->Release()
1621 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1623 DWORD shaderflags = 0;
1625 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1626 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1627 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1628 if (vertstring && vertstring[0])
1632 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1633 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1636 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1639 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1640 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1641 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1642 ID3DXBuffer_Release(vsbuffer);
1646 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1647 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1648 ID3DXBuffer_Release(vslog);
1651 if (fragstring && fragstring[0])
1655 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1656 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1659 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1662 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1663 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1664 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1665 ID3DXBuffer_Release(psbuffer);
1669 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1670 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1671 ID3DXBuffer_Release(pslog);
1674 Sys_UnloadLibrary(&d3dx9_dll);
1677 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1681 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1682 if (FAILED(vsresult))
1683 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1684 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1685 if (FAILED(psresult))
1686 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1688 // free the shader data
1689 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1690 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1693 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1696 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1697 int vertstring_length = 0;
1698 int geomstring_length = 0;
1699 int fragstring_length = 0;
1702 char *vertstring, *geomstring, *fragstring;
1703 char permutationname[256];
1704 char cachename[256];
1705 int vertstrings_count = 0;
1706 int geomstrings_count = 0;
1707 int fragstrings_count = 0;
1708 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1709 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1710 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1715 p->vertexshader = NULL;
1716 p->pixelshader = NULL;
1718 permutationname[0] = 0;
1720 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1722 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1723 strlcat(cachename, "hlsl/", sizeof(cachename));
1725 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1726 vertstrings_count = 0;
1727 geomstrings_count = 0;
1728 fragstrings_count = 0;
1729 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1730 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1731 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1733 // the first pretext is which type of shader to compile as
1734 // (later these will all be bound together as a program object)
1735 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1736 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1737 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1739 // the second pretext is the mode (for example a light source)
1740 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1741 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1742 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1743 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1744 strlcat(cachename, modeinfo->name, sizeof(cachename));
1746 // now add all the permutation pretexts
1747 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1749 if (permutation & (1<<i))
1751 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1752 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1753 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1754 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1755 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1759 // keep line numbers correct
1760 vertstrings_list[vertstrings_count++] = "\n";
1761 geomstrings_list[geomstrings_count++] = "\n";
1762 fragstrings_list[fragstrings_count++] = "\n";
1767 R_CompileShader_AddStaticParms(mode, permutation);
1768 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1769 vertstrings_count += shaderstaticparms_count;
1770 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1771 geomstrings_count += shaderstaticparms_count;
1772 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1773 fragstrings_count += shaderstaticparms_count;
1775 // replace spaces in the cachename with _ characters
1776 for (i = 0;cachename[i];i++)
1777 if (cachename[i] == ' ')
1780 // now append the shader text itself
1781 vertstrings_list[vertstrings_count++] = sourcestring;
1782 geomstrings_list[geomstrings_count++] = sourcestring;
1783 fragstrings_list[fragstrings_count++] = sourcestring;
1785 vertstring_length = 0;
1786 for (i = 0;i < vertstrings_count;i++)
1787 vertstring_length += (int)strlen(vertstrings_list[i]);
1788 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1789 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1790 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1792 geomstring_length = 0;
1793 for (i = 0;i < geomstrings_count;i++)
1794 geomstring_length += (int)strlen(geomstrings_list[i]);
1795 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1796 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1797 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1799 fragstring_length = 0;
1800 for (i = 0;i < fragstrings_count;i++)
1801 fragstring_length += (int)strlen(fragstrings_list[i]);
1802 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1803 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1804 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1806 // try to load the cached shader, or generate one
1807 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1809 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1810 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1812 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1816 Mem_Free(vertstring);
1818 Mem_Free(geomstring);
1820 Mem_Free(fragstring);
1822 Mem_Free(sourcestring);
1825 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1826 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1827 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);}
1828 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);}
1829 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);}
1830 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);}
1832 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1833 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1834 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);}
1835 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);}
1836 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);}
1837 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);}
1839 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1841 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1842 if (r_hlsl_permutation != perm)
1844 r_hlsl_permutation = perm;
1845 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1847 if (!r_hlsl_permutation->compiled)
1848 R_HLSL_CompilePermutation(perm, mode, permutation);
1849 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1851 // remove features until we find a valid permutation
1853 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1855 // reduce i more quickly whenever it would not remove any bits
1856 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1857 if (!(permutation & j))
1860 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1861 if (!r_hlsl_permutation->compiled)
1862 R_HLSL_CompilePermutation(perm, mode, permutation);
1863 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1866 if (i >= SHADERPERMUTATION_COUNT)
1868 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1869 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1870 return; // no bit left to clear, entire mode is broken
1874 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1875 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1877 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1878 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1879 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1883 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1885 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1886 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1887 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1888 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1891 void R_GLSL_Restart_f(void)
1893 unsigned int i, limit;
1894 switch(vid.renderpath)
1896 case RENDERPATH_D3D9:
1899 r_hlsl_permutation_t *p;
1900 r_hlsl_permutation = NULL;
1901 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1902 for (i = 0;i < limit;i++)
1904 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1906 if (p->vertexshader)
1907 IDirect3DVertexShader9_Release(p->vertexshader);
1909 IDirect3DPixelShader9_Release(p->pixelshader);
1910 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1913 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1917 case RENDERPATH_D3D10:
1918 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920 case RENDERPATH_D3D11:
1921 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1923 case RENDERPATH_GL20:
1924 case RENDERPATH_GLES2:
1926 r_glsl_permutation_t *p;
1927 r_glsl_permutation = NULL;
1928 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1929 for (i = 0;i < limit;i++)
1931 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1933 GL_Backend_FreeProgram(p->program);
1934 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1937 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1940 case RENDERPATH_GL11:
1941 case RENDERPATH_GL13:
1942 case RENDERPATH_GLES1:
1944 case RENDERPATH_SOFT:
1949 static void R_GLSL_DumpShader_f(void)
1951 int i, language, mode, dupe;
1953 shadermodeinfo_t *modeinfo;
1956 for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1958 modeinfo = shadermodeinfo[language];
1959 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1961 // don't dump the same file multiple times (most or all shaders come from the same file)
1962 for (dupe = mode - 1;dupe >= 0;dupe--)
1963 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1967 text = modeinfo[mode].builtinstring;
1970 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1973 FS_Print(file, "/* The engine may define the following macros:\n");
1974 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1975 for (i = 0;i < SHADERMODE_COUNT;i++)
1976 FS_Print(file, modeinfo[i].pretext);
1977 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1978 FS_Print(file, shaderpermutationinfo[i].pretext);
1979 FS_Print(file, "*/\n");
1980 FS_Print(file, text);
1982 Con_Printf("%s written\n", modeinfo[mode].filename);
1985 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1990 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1992 unsigned int permutation = 0;
1993 if (r_trippy.integer && !notrippy)
1994 permutation |= SHADERPERMUTATION_TRIPPY;
1995 permutation |= SHADERPERMUTATION_VIEWTINT;
1997 permutation |= SHADERPERMUTATION_DIFFUSE;
1999 permutation |= SHADERPERMUTATION_SPECULAR;
2000 if (texturemode == GL_MODULATE)
2001 permutation |= SHADERPERMUTATION_COLORMAPPING;
2002 else if (texturemode == GL_ADD)
2003 permutation |= SHADERPERMUTATION_GLOW;
2004 else if (texturemode == GL_DECAL)
2005 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2006 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2007 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2008 if (suppresstexalpha)
2009 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2011 texturemode = GL_MODULATE;
2012 if (vid.allowalphatocoverage)
2013 GL_AlphaToCoverage(false);
2014 switch (vid.renderpath)
2016 case RENDERPATH_D3D9:
2018 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2019 R_Mesh_TexBind(GL20TU_FIRST , first );
2020 R_Mesh_TexBind(GL20TU_SECOND, second);
2021 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2022 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2025 case RENDERPATH_D3D10:
2026 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2028 case RENDERPATH_D3D11:
2029 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2031 case RENDERPATH_GL20:
2032 case RENDERPATH_GLES2:
2033 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2034 if (r_glsl_permutation->tex_Texture_First >= 0)
2035 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2036 if (r_glsl_permutation->tex_Texture_Second >= 0)
2037 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2038 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2039 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2041 case RENDERPATH_GL13:
2042 case RENDERPATH_GLES1:
2043 R_Mesh_TexBind(0, first );
2044 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2045 R_Mesh_TexMatrix(0, NULL);
2046 R_Mesh_TexBind(1, second);
2049 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2050 R_Mesh_TexMatrix(1, NULL);
2053 case RENDERPATH_GL11:
2054 R_Mesh_TexBind(0, first );
2055 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2056 R_Mesh_TexMatrix(0, NULL);
2058 case RENDERPATH_SOFT:
2059 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2060 R_Mesh_TexBind(GL20TU_FIRST , first );
2061 R_Mesh_TexBind(GL20TU_SECOND, second);
2066 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2068 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2071 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2073 unsigned int permutation = 0;
2074 if (r_trippy.integer && !notrippy)
2075 permutation |= SHADERPERMUTATION_TRIPPY;
2077 permutation |= SHADERPERMUTATION_DEPTHRGB;
2079 permutation |= SHADERPERMUTATION_SKELETAL;
2081 if (vid.allowalphatocoverage)
2082 GL_AlphaToCoverage(false);
2083 switch (vid.renderpath)
2085 case RENDERPATH_D3D9:
2087 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2090 case RENDERPATH_D3D10:
2091 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2093 case RENDERPATH_D3D11:
2094 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2096 case RENDERPATH_GL20:
2097 case RENDERPATH_GLES2:
2098 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2099 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2100 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);
2103 case RENDERPATH_GL13:
2104 case RENDERPATH_GLES1:
2105 R_Mesh_TexBind(0, 0);
2106 R_Mesh_TexBind(1, 0);
2108 case RENDERPATH_GL11:
2109 R_Mesh_TexBind(0, 0);
2111 case RENDERPATH_SOFT:
2112 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2117 extern qboolean r_shadow_usingdeferredprepass;
2118 extern rtexture_t *r_shadow_attenuationgradienttexture;
2119 extern rtexture_t *r_shadow_attenuation2dtexture;
2120 extern rtexture_t *r_shadow_attenuation3dtexture;
2121 extern qboolean r_shadow_usingshadowmap2d;
2122 extern qboolean r_shadow_usingshadowmaportho;
2123 extern float r_shadow_modelshadowmap_texturescale[4];
2124 extern float r_shadow_modelshadowmap_parameters[4];
2125 extern float r_shadow_lightshadowmap_texturescale[4];
2126 extern float r_shadow_lightshadowmap_parameters[4];
2127 extern qboolean r_shadow_shadowmapvsdct;
2128 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2129 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2130 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2131 extern matrix4x4_t r_shadow_shadowmapmatrix;
2132 extern int r_shadow_prepass_width;
2133 extern int r_shadow_prepass_height;
2134 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2135 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2136 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2137 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2139 #define BLENDFUNC_ALLOWS_COLORMOD 1
2140 #define BLENDFUNC_ALLOWS_FOG 2
2141 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2142 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2143 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2144 static int R_BlendFuncFlags(int src, int dst)
2148 // a blendfunc allows colormod if:
2149 // a) it can never keep the destination pixel invariant, or
2150 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2151 // this is to prevent unintended side effects from colormod
2153 // a blendfunc allows fog if:
2154 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2155 // this is to prevent unintended side effects from fog
2157 // these checks are the output of fogeval.pl
2159 r |= BLENDFUNC_ALLOWS_COLORMOD;
2160 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2161 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2162 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2163 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2164 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2165 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2166 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2167 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2168 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2169 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2170 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2171 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2173 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2174 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2175 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2176 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2177 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2178 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2179 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2180 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2185 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2187 // select a permutation of the lighting shader appropriate to this
2188 // combination of texture, entity, light source, and fogging, only use the
2189 // minimum features necessary to avoid wasting rendering time in the
2190 // fragment shader on features that are not being used
2191 unsigned int permutation = 0;
2192 unsigned int mode = 0;
2194 static float dummy_colormod[3] = {1, 1, 1};
2195 float *colormod = rsurface.colormod;
2197 matrix4x4_t tempmatrix;
2198 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2199 if (r_trippy.integer && !notrippy)
2200 permutation |= SHADERPERMUTATION_TRIPPY;
2201 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2202 permutation |= SHADERPERMUTATION_ALPHAKILL;
2203 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2204 permutation |= SHADERPERMUTATION_OCCLUDE;
2205 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2206 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2207 if (rsurfacepass == RSURFPASS_BACKGROUND)
2209 // distorted background
2210 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2212 mode = SHADERMODE_WATER;
2213 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2214 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2215 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2217 // this is the right thing to do for wateralpha
2218 GL_BlendFunc(GL_ONE, GL_ZERO);
2219 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2223 // this is the right thing to do for entity alpha
2224 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2225 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2228 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2230 mode = SHADERMODE_REFRACTION;
2231 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2232 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2233 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2234 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2238 mode = SHADERMODE_GENERIC;
2239 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2240 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2243 if (vid.allowalphatocoverage)
2244 GL_AlphaToCoverage(false);
2246 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2248 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2250 switch(rsurface.texture->offsetmapping)
2252 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2253 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2254 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2255 case OFFSETMAPPING_OFF: break;
2258 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2259 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2260 // normalmap (deferred prepass), may use alpha test on diffuse
2261 mode = SHADERMODE_DEFERREDGEOMETRY;
2262 GL_BlendFunc(GL_ONE, GL_ZERO);
2263 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2264 if (vid.allowalphatocoverage)
2265 GL_AlphaToCoverage(false);
2267 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2269 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2271 switch(rsurface.texture->offsetmapping)
2273 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2274 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2275 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2276 case OFFSETMAPPING_OFF: break;
2279 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2280 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2281 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2282 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2284 mode = SHADERMODE_LIGHTSOURCE;
2285 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2286 permutation |= SHADERPERMUTATION_CUBEFILTER;
2287 if (diffusescale > 0)
2288 permutation |= SHADERPERMUTATION_DIFFUSE;
2289 if (specularscale > 0)
2290 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2291 if (r_refdef.fogenabled)
2292 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2293 if (rsurface.texture->colormapping)
2294 permutation |= SHADERPERMUTATION_COLORMAPPING;
2295 if (r_shadow_usingshadowmap2d)
2297 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2298 if(r_shadow_shadowmapvsdct)
2299 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2301 if (r_shadow_shadowmap2ddepthbuffer)
2302 permutation |= SHADERPERMUTATION_DEPTHRGB;
2304 if (rsurface.texture->reflectmasktexture)
2305 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2306 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2307 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2308 if (vid.allowalphatocoverage)
2309 GL_AlphaToCoverage(false);
2311 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2313 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2315 switch(rsurface.texture->offsetmapping)
2317 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2318 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2319 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2320 case OFFSETMAPPING_OFF: break;
2323 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2324 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2325 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2326 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2327 // unshaded geometry (fullbright or ambient model lighting)
2328 mode = SHADERMODE_FLATCOLOR;
2329 ambientscale = diffusescale = specularscale = 0;
2330 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2331 permutation |= SHADERPERMUTATION_GLOW;
2332 if (r_refdef.fogenabled)
2333 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2334 if (rsurface.texture->colormapping)
2335 permutation |= SHADERPERMUTATION_COLORMAPPING;
2336 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2338 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2339 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2341 if (r_shadow_shadowmap2ddepthbuffer)
2342 permutation |= SHADERPERMUTATION_DEPTHRGB;
2344 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2345 permutation |= SHADERPERMUTATION_REFLECTION;
2346 if (rsurface.texture->reflectmasktexture)
2347 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2348 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2349 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2350 // when using alphatocoverage, we don't need alphakill
2351 if (vid.allowalphatocoverage)
2353 if (r_transparent_alphatocoverage.integer)
2355 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2356 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2359 GL_AlphaToCoverage(false);
2362 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2364 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2366 switch(rsurface.texture->offsetmapping)
2368 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2369 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2370 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2371 case OFFSETMAPPING_OFF: break;
2374 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2375 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2376 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2377 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2378 // directional model lighting
2379 mode = SHADERMODE_LIGHTDIRECTION;
2380 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2381 permutation |= SHADERPERMUTATION_GLOW;
2382 permutation |= SHADERPERMUTATION_DIFFUSE;
2383 if (specularscale > 0)
2384 permutation |= SHADERPERMUTATION_SPECULAR;
2385 if (r_refdef.fogenabled)
2386 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2387 if (rsurface.texture->colormapping)
2388 permutation |= SHADERPERMUTATION_COLORMAPPING;
2389 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2391 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2392 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2394 if (r_shadow_shadowmap2ddepthbuffer)
2395 permutation |= SHADERPERMUTATION_DEPTHRGB;
2397 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2398 permutation |= SHADERPERMUTATION_REFLECTION;
2399 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2400 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2401 if (rsurface.texture->reflectmasktexture)
2402 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2403 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2405 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2406 if (r_shadow_bouncegrid_state.directional)
2407 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2409 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2410 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2411 // when using alphatocoverage, we don't need alphakill
2412 if (vid.allowalphatocoverage)
2414 if (r_transparent_alphatocoverage.integer)
2416 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2417 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2420 GL_AlphaToCoverage(false);
2423 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2425 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2427 switch(rsurface.texture->offsetmapping)
2429 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2430 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2431 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2432 case OFFSETMAPPING_OFF: break;
2435 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2436 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2437 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2438 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2439 // ambient model lighting
2440 mode = SHADERMODE_LIGHTDIRECTION;
2441 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2442 permutation |= SHADERPERMUTATION_GLOW;
2443 if (r_refdef.fogenabled)
2444 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2445 if (rsurface.texture->colormapping)
2446 permutation |= SHADERPERMUTATION_COLORMAPPING;
2447 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2449 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2450 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2452 if (r_shadow_shadowmap2ddepthbuffer)
2453 permutation |= SHADERPERMUTATION_DEPTHRGB;
2455 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2456 permutation |= SHADERPERMUTATION_REFLECTION;
2457 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2458 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2459 if (rsurface.texture->reflectmasktexture)
2460 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2461 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2463 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2464 if (r_shadow_bouncegrid_state.directional)
2465 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2467 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2468 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2469 // when using alphatocoverage, we don't need alphakill
2470 if (vid.allowalphatocoverage)
2472 if (r_transparent_alphatocoverage.integer)
2474 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2475 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2478 GL_AlphaToCoverage(false);
2483 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2485 switch(rsurface.texture->offsetmapping)
2487 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2488 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2489 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2490 case OFFSETMAPPING_OFF: break;
2493 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2494 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2495 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2496 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2498 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2499 permutation |= SHADERPERMUTATION_GLOW;
2500 if (r_refdef.fogenabled)
2501 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2502 if (rsurface.texture->colormapping)
2503 permutation |= SHADERPERMUTATION_COLORMAPPING;
2504 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2506 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2507 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2509 if (r_shadow_shadowmap2ddepthbuffer)
2510 permutation |= SHADERPERMUTATION_DEPTHRGB;
2512 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2513 permutation |= SHADERPERMUTATION_REFLECTION;
2514 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2515 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2516 if (rsurface.texture->reflectmasktexture)
2517 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2518 if (FAKELIGHT_ENABLED)
2520 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2521 mode = SHADERMODE_FAKELIGHT;
2522 permutation |= SHADERPERMUTATION_DIFFUSE;
2523 if (specularscale > 0)
2524 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2526 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2528 // deluxemapping (light direction texture)
2529 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2530 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2532 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2533 permutation |= SHADERPERMUTATION_DIFFUSE;
2534 if (specularscale > 0)
2535 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2537 else if (r_glsl_deluxemapping.integer >= 2)
2539 // fake deluxemapping (uniform light direction in tangentspace)
2540 if (rsurface.uselightmaptexture)
2541 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2543 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2544 permutation |= SHADERPERMUTATION_DIFFUSE;
2545 if (specularscale > 0)
2546 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2548 else if (rsurface.uselightmaptexture)
2550 // ordinary lightmapping (q1bsp, q3bsp)
2551 mode = SHADERMODE_LIGHTMAP;
2555 // ordinary vertex coloring (q3bsp)
2556 mode = SHADERMODE_VERTEXCOLOR;
2558 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2560 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2561 if (r_shadow_bouncegrid_state.directional)
2562 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2564 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2565 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2566 // when using alphatocoverage, we don't need alphakill
2567 if (vid.allowalphatocoverage)
2569 if (r_transparent_alphatocoverage.integer)
2571 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2572 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2575 GL_AlphaToCoverage(false);
2578 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2579 colormod = dummy_colormod;
2580 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2581 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2582 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2583 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2584 switch(vid.renderpath)
2586 case RENDERPATH_D3D9:
2588 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);
2589 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2590 R_SetupShader_SetPermutationHLSL(mode, permutation);
2591 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2592 if (mode == SHADERMODE_LIGHTSOURCE)
2594 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2595 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2599 if (mode == SHADERMODE_LIGHTDIRECTION)
2601 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2604 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2605 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2606 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2607 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2608 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2610 if (mode == SHADERMODE_LIGHTSOURCE)
2612 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2613 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2614 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2615 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2616 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2618 // additive passes are only darkened by fog, not tinted
2619 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2620 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2624 if (mode == SHADERMODE_FLATCOLOR)
2626 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2628 else if (mode == SHADERMODE_LIGHTDIRECTION)
2630 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2631 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2632 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2633 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2634 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2635 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2636 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2640 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2641 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2642 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2643 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2644 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2646 // additive passes are only darkened by fog, not tinted
2647 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2648 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2650 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2651 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2652 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2653 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2654 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2655 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2656 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2657 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2658 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2659 if (mode == SHADERMODE_WATER)
2660 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2662 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2664 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2665 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2669 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2670 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2672 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2673 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2674 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2675 if (rsurface.texture->pantstexture)
2676 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2678 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2679 if (rsurface.texture->shirttexture)
2680 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2682 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2683 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2684 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2685 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2686 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2687 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2688 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2689 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2690 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2691 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2693 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2694 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2695 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2696 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2698 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2699 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2700 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2701 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2702 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2703 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2704 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2705 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2706 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2707 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2708 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2709 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2710 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2711 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2712 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2713 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2714 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2715 if (rsurfacepass == RSURFPASS_BACKGROUND)
2717 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2718 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2719 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2723 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2725 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2726 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2727 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2728 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2730 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2731 if (rsurface.rtlight)
2733 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2734 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2739 case RENDERPATH_D3D10:
2740 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2742 case RENDERPATH_D3D11:
2743 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2745 case RENDERPATH_GL20:
2746 case RENDERPATH_GLES2:
2747 if (!vid.useinterleavedarrays)
2749 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);
2750 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2751 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2752 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2753 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2754 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2755 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2756 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2757 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2758 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2759 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2763 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);
2764 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2766 // this has to be after RSurf_PrepareVerticesForBatch
2767 if (rsurface.batchskeletaltransform3x4buffer)
2768 permutation |= SHADERPERMUTATION_SKELETAL;
2769 R_SetupShader_SetPermutationGLSL(mode, permutation);
2770 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2771 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);
2773 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2774 if (mode == SHADERMODE_LIGHTSOURCE)
2776 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2777 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2778 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2779 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2780 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2781 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2783 // additive passes are only darkened by fog, not tinted
2784 if (r_glsl_permutation->loc_FogColor >= 0)
2785 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2786 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2790 if (mode == SHADERMODE_FLATCOLOR)
2792 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2794 else if (mode == SHADERMODE_LIGHTDIRECTION)
2796 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2797 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2798 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2799 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2800 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2801 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2802 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2806 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2807 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2808 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2809 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2810 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2812 // additive passes are only darkened by fog, not tinted
2813 if (r_glsl_permutation->loc_FogColor >= 0)
2815 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2816 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2818 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2820 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2821 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]);
2822 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]);
2823 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2824 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2825 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2826 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2827 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2828 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2830 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2831 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2832 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2833 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2835 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]);
2836 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]);
2840 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]);
2841 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]);
2844 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2845 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2846 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2847 if (r_glsl_permutation->loc_Color_Pants >= 0)
2849 if (rsurface.texture->pantstexture)
2850 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2852 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2854 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2856 if (rsurface.texture->shirttexture)
2857 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2859 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2861 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]);
2862 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2863 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2864 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2865 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2866 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2867 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2868 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2869 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2871 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);
2872 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2873 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]);
2874 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2875 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);}
2876 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2878 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2879 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2880 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2881 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2882 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2883 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2884 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2885 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2886 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2887 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2888 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2889 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2890 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2891 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2892 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2893 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2894 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2895 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2896 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2897 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2898 if (rsurfacepass == RSURFPASS_BACKGROUND)
2900 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2901 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2902 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2906 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2908 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2909 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2910 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2911 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2913 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2914 if (rsurface.rtlight)
2916 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2917 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2920 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2923 case RENDERPATH_GL11:
2924 case RENDERPATH_GL13:
2925 case RENDERPATH_GLES1:
2927 case RENDERPATH_SOFT:
2928 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);
2929 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2930 R_SetupShader_SetPermutationSoft(mode, permutation);
2931 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2932 if (mode == SHADERMODE_LIGHTSOURCE)
2934 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2935 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2936 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2937 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2938 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2939 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2941 // additive passes are only darkened by fog, not tinted
2942 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2943 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2947 if (mode == SHADERMODE_FLATCOLOR)
2949 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2951 else if (mode == SHADERMODE_LIGHTDIRECTION)
2953 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2954 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2955 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2956 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2957 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2958 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2959 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2963 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2964 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2965 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2966 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2967 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2969 // additive passes are only darkened by fog, not tinted
2970 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2971 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2973 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2974 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2975 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]);
2976 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]);
2977 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2978 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2979 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2980 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2981 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2982 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2984 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2985 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2986 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2987 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2989 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]);
2990 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]);
2994 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]);
2995 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]);
2998 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2999 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
3000 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3001 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3003 if (rsurface.texture->pantstexture)
3004 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3006 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3008 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3010 if (rsurface.texture->shirttexture)
3011 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3013 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3015 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3016 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3017 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3018 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3019 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3020 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3021 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3022 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3023 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3025 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3026 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3027 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3028 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3030 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3031 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3032 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3033 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3034 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3035 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3036 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3037 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3038 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3039 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3040 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3041 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3042 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3043 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3044 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3045 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3046 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3047 if (rsurfacepass == RSURFPASS_BACKGROUND)
3049 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3050 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3051 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3055 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3057 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3058 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3059 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3060 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3062 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3063 if (rsurface.rtlight)
3065 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3066 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3073 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3075 // select a permutation of the lighting shader appropriate to this
3076 // combination of texture, entity, light source, and fogging, only use the
3077 // minimum features necessary to avoid wasting rendering time in the
3078 // fragment shader on features that are not being used
3079 unsigned int permutation = 0;
3080 unsigned int mode = 0;
3081 const float *lightcolorbase = rtlight->currentcolor;
3082 float ambientscale = rtlight->ambientscale;
3083 float diffusescale = rtlight->diffusescale;
3084 float specularscale = rtlight->specularscale;
3085 // this is the location of the light in view space
3086 vec3_t viewlightorigin;
3087 // this transforms from view space (camera) to light space (cubemap)
3088 matrix4x4_t viewtolight;
3089 matrix4x4_t lighttoview;
3090 float viewtolight16f[16];
3092 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3093 if (rtlight->currentcubemap != r_texture_whitecube)
3094 permutation |= SHADERPERMUTATION_CUBEFILTER;
3095 if (diffusescale > 0)
3096 permutation |= SHADERPERMUTATION_DIFFUSE;
3097 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3098 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3099 if (r_shadow_usingshadowmap2d)
3101 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3102 if (r_shadow_shadowmapvsdct)
3103 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3105 if (r_shadow_shadowmap2ddepthbuffer)
3106 permutation |= SHADERPERMUTATION_DEPTHRGB;
3108 if (vid.allowalphatocoverage)
3109 GL_AlphaToCoverage(false);
3110 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3111 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3112 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3113 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3114 switch(vid.renderpath)
3116 case RENDERPATH_D3D9:
3118 R_SetupShader_SetPermutationHLSL(mode, permutation);
3119 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3120 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3121 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3122 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3123 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3124 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3125 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3126 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);
3127 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3128 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3130 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3131 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3132 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3133 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3134 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3137 case RENDERPATH_D3D10:
3138 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3140 case RENDERPATH_D3D11:
3141 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3143 case RENDERPATH_GL20:
3144 case RENDERPATH_GLES2:
3145 R_SetupShader_SetPermutationGLSL(mode, permutation);
3146 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3147 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3148 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3149 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3150 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3151 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]);
3152 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]);
3153 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);
3154 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]);
3155 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3157 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3158 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3159 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3160 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3161 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3163 case RENDERPATH_GL11:
3164 case RENDERPATH_GL13:
3165 case RENDERPATH_GLES1:
3167 case RENDERPATH_SOFT:
3168 R_SetupShader_SetPermutationGLSL(mode, permutation);
3169 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3170 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3171 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3172 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3173 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3174 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]);
3175 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]);
3176 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);
3177 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3178 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3180 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3181 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3182 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3183 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3184 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3189 #define SKINFRAME_HASH 1024
3193 unsigned int loadsequence; // incremented each level change
3194 memexpandablearray_t array;
3195 skinframe_t *hash[SKINFRAME_HASH];
3198 r_skinframe_t r_skinframe;
3200 void R_SkinFrame_PrepareForPurge(void)
3202 r_skinframe.loadsequence++;
3203 // wrap it without hitting zero
3204 if (r_skinframe.loadsequence >= 200)
3205 r_skinframe.loadsequence = 1;
3208 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3212 // mark the skinframe as used for the purging code
3213 skinframe->loadsequence = r_skinframe.loadsequence;
3216 void R_SkinFrame_Purge(void)
3220 for (i = 0;i < SKINFRAME_HASH;i++)
3222 for (s = r_skinframe.hash[i];s;s = s->next)
3224 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3226 if (s->merged == s->base)
3228 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3229 R_PurgeTexture(s->stain );s->stain = NULL;
3230 R_PurgeTexture(s->merged);s->merged = NULL;
3231 R_PurgeTexture(s->base );s->base = NULL;
3232 R_PurgeTexture(s->pants );s->pants = NULL;
3233 R_PurgeTexture(s->shirt );s->shirt = NULL;
3234 R_PurgeTexture(s->nmap );s->nmap = NULL;
3235 R_PurgeTexture(s->gloss );s->gloss = NULL;
3236 R_PurgeTexture(s->glow );s->glow = NULL;
3237 R_PurgeTexture(s->fog );s->fog = NULL;
3238 R_PurgeTexture(s->reflect);s->reflect = NULL;
3239 s->loadsequence = 0;
3245 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3247 char basename[MAX_QPATH];
3249 Image_StripImageExtension(name, basename, sizeof(basename));
3251 if( last == NULL ) {
3253 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3254 item = r_skinframe.hash[hashindex];
3259 // linearly search through the hash bucket
3260 for( ; item ; item = item->next ) {
3261 if( !strcmp( item->basename, basename ) ) {
3268 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3272 char basename[MAX_QPATH];
3274 Image_StripImageExtension(name, basename, sizeof(basename));
3276 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3277 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3278 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3282 rtexture_t *dyntexture;
3283 // check whether its a dynamic texture
3284 dyntexture = CL_GetDynTexture( basename );
3285 if (!add && !dyntexture)
3287 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3288 memset(item, 0, sizeof(*item));
3289 strlcpy(item->basename, basename, sizeof(item->basename));
3290 item->base = dyntexture; // either NULL or dyntexture handle
3291 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3292 item->comparewidth = comparewidth;
3293 item->compareheight = compareheight;
3294 item->comparecrc = comparecrc;
3295 item->next = r_skinframe.hash[hashindex];
3296 r_skinframe.hash[hashindex] = item;
3298 else if (textureflags & TEXF_FORCE_RELOAD)
3300 rtexture_t *dyntexture;
3301 // check whether its a dynamic texture
3302 dyntexture = CL_GetDynTexture( basename );
3303 if (!add && !dyntexture)
3305 if (item->merged == item->base)
3306 item->merged = NULL;
3307 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3308 R_PurgeTexture(item->stain );item->stain = NULL;
3309 R_PurgeTexture(item->merged);item->merged = NULL;
3310 R_PurgeTexture(item->base );item->base = NULL;
3311 R_PurgeTexture(item->pants );item->pants = NULL;
3312 R_PurgeTexture(item->shirt );item->shirt = NULL;
3313 R_PurgeTexture(item->nmap );item->nmap = NULL;
3314 R_PurgeTexture(item->gloss );item->gloss = NULL;
3315 R_PurgeTexture(item->glow );item->glow = NULL;
3316 R_PurgeTexture(item->fog );item->fog = NULL;
3317 R_PurgeTexture(item->reflect);item->reflect = NULL;
3318 item->loadsequence = 0;
3320 else if( item->base == NULL )
3322 rtexture_t *dyntexture;
3323 // check whether its a dynamic texture
3324 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3325 dyntexture = CL_GetDynTexture( basename );
3326 item->base = dyntexture; // either NULL or dyntexture handle
3329 R_SkinFrame_MarkUsed(item);
3333 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3335 unsigned long long avgcolor[5], wsum; \
3343 for(pix = 0; pix < cnt; ++pix) \
3346 for(comp = 0; comp < 3; ++comp) \
3348 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3351 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3353 for(comp = 0; comp < 3; ++comp) \
3354 avgcolor[comp] += getpixel * w; \
3357 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3358 avgcolor[4] += getpixel; \
3360 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3362 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3363 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3364 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3365 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3368 extern cvar_t gl_picmip;
3369 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3372 unsigned char *pixels;
3373 unsigned char *bumppixels;
3374 unsigned char *basepixels = NULL;
3375 int basepixels_width = 0;
3376 int basepixels_height = 0;
3377 skinframe_t *skinframe;
3378 rtexture_t *ddsbase = NULL;
3379 qboolean ddshasalpha = false;
3380 float ddsavgcolor[4];
3381 char basename[MAX_QPATH];
3382 int miplevel = R_PicmipForFlags(textureflags);
3383 int savemiplevel = miplevel;
3387 if (cls.state == ca_dedicated)
3390 // return an existing skinframe if already loaded
3391 // if loading of the first image fails, don't make a new skinframe as it
3392 // would cause all future lookups of this to be missing
3393 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3394 if (skinframe && skinframe->base)
3397 Image_StripImageExtension(name, basename, sizeof(basename));
3399 // check for DDS texture file first
3400 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3402 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3403 if (basepixels == NULL)
3407 // FIXME handle miplevel
3409 if (developer_loading.integer)
3410 Con_Printf("loading skin \"%s\"\n", name);
3412 // we've got some pixels to store, so really allocate this new texture now
3414 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3415 textureflags &= ~TEXF_FORCE_RELOAD;
3416 skinframe->stain = NULL;
3417 skinframe->merged = NULL;
3418 skinframe->base = NULL;
3419 skinframe->pants = NULL;
3420 skinframe->shirt = NULL;
3421 skinframe->nmap = NULL;
3422 skinframe->gloss = NULL;
3423 skinframe->glow = NULL;
3424 skinframe->fog = NULL;
3425 skinframe->reflect = NULL;
3426 skinframe->hasalpha = false;
3427 // we could store the q2animname here too
3431 skinframe->base = ddsbase;
3432 skinframe->hasalpha = ddshasalpha;
3433 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3434 if (r_loadfog && skinframe->hasalpha)
3435 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);
3436 //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]);
3440 basepixels_width = image_width;
3441 basepixels_height = image_height;
3442 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);
3443 if (textureflags & TEXF_ALPHA)
3445 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3447 if (basepixels[j] < 255)
3449 skinframe->hasalpha = true;
3453 if (r_loadfog && skinframe->hasalpha)
3455 // has transparent pixels
3456 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3457 for (j = 0;j < image_width * image_height * 4;j += 4)
3462 pixels[j+3] = basepixels[j+3];
3464 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);
3468 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3470 //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]);
3471 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3472 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3473 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3474 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3480 mymiplevel = savemiplevel;
3481 if (r_loadnormalmap)
3482 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);
3483 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3485 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3486 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3487 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3488 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3491 // _norm is the name used by tenebrae and has been adopted as standard
3492 if (r_loadnormalmap && skinframe->nmap == NULL)
3494 mymiplevel = savemiplevel;
3495 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3497 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);
3501 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3503 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3504 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3505 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);
3507 Mem_Free(bumppixels);
3509 else if (r_shadow_bumpscale_basetexture.value > 0)
3511 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3512 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3513 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);
3517 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3518 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3522 // _luma is supported only for tenebrae compatibility
3523 // _glow is the preferred name
3524 mymiplevel = savemiplevel;
3525 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))))
3527 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);
3529 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3530 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3532 Mem_Free(pixels);pixels = NULL;
3535 mymiplevel = savemiplevel;
3536 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3538 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);
3540 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3541 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3547 mymiplevel = savemiplevel;
3548 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3550 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);
3552 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3553 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3559 mymiplevel = savemiplevel;
3560 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3562 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);
3564 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3565 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3571 mymiplevel = savemiplevel;
3572 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3574 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);
3576 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3577 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3584 Mem_Free(basepixels);
3589 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3590 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3593 skinframe_t *skinframe;
3596 if (cls.state == ca_dedicated)
3599 // if already loaded just return it, otherwise make a new skinframe
3600 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3601 if (skinframe->base)
3603 textureflags &= ~TEXF_FORCE_RELOAD;
3605 skinframe->stain = NULL;
3606 skinframe->merged = NULL;
3607 skinframe->base = NULL;
3608 skinframe->pants = NULL;
3609 skinframe->shirt = NULL;
3610 skinframe->nmap = NULL;
3611 skinframe->gloss = NULL;
3612 skinframe->glow = NULL;
3613 skinframe->fog = NULL;
3614 skinframe->reflect = NULL;
3615 skinframe->hasalpha = false;
3617 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3621 if (developer_loading.integer)
3622 Con_Printf("loading 32bit skin \"%s\"\n", name);
3624 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3626 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3627 unsigned char *b = a + width * height * 4;
3628 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3629 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);
3632 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3633 if (textureflags & TEXF_ALPHA)
3635 for (i = 3;i < width * height * 4;i += 4)
3637 if (skindata[i] < 255)
3639 skinframe->hasalpha = true;
3643 if (r_loadfog && skinframe->hasalpha)
3645 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3646 memcpy(fogpixels, skindata, width * height * 4);
3647 for (i = 0;i < width * height * 4;i += 4)
3648 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3649 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3650 Mem_Free(fogpixels);
3654 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3655 //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]);
3660 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3664 skinframe_t *skinframe;
3666 if (cls.state == ca_dedicated)
3669 // if already loaded just return it, otherwise make a new skinframe
3670 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3671 if (skinframe->base)
3673 //textureflags &= ~TEXF_FORCE_RELOAD;
3675 skinframe->stain = NULL;
3676 skinframe->merged = NULL;
3677 skinframe->base = NULL;
3678 skinframe->pants = NULL;
3679 skinframe->shirt = NULL;
3680 skinframe->nmap = NULL;
3681 skinframe->gloss = NULL;
3682 skinframe->glow = NULL;
3683 skinframe->fog = NULL;
3684 skinframe->reflect = NULL;
3685 skinframe->hasalpha = false;
3687 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3691 if (developer_loading.integer)
3692 Con_Printf("loading quake skin \"%s\"\n", name);
3694 // 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)
3695 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3696 memcpy(skinframe->qpixels, skindata, width*height);
3697 skinframe->qwidth = width;
3698 skinframe->qheight = height;
3701 for (i = 0;i < width * height;i++)
3702 featuresmask |= palette_featureflags[skindata[i]];
3704 skinframe->hasalpha = false;
3707 skinframe->hasalpha = true;
3708 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3709 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3710 skinframe->qgeneratemerged = true;
3711 skinframe->qgeneratebase = skinframe->qhascolormapping;
3712 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3714 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3715 //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]);
3720 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3724 unsigned char *skindata;
3727 if (!skinframe->qpixels)
3730 if (!skinframe->qhascolormapping)
3731 colormapped = false;
3735 if (!skinframe->qgeneratebase)
3740 if (!skinframe->qgeneratemerged)
3744 width = skinframe->qwidth;
3745 height = skinframe->qheight;
3746 skindata = skinframe->qpixels;
3748 if (skinframe->qgeneratenmap)
3750 unsigned char *a, *b;
3751 skinframe->qgeneratenmap = false;
3752 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3753 b = a + width * height * 4;
3754 // use either a custom palette or the quake palette
3755 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3756 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3757 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);
3761 if (skinframe->qgenerateglow)
3763 skinframe->qgenerateglow = false;
3764 if (skinframe->hasalpha) // fence textures
3765 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
3767 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
3772 skinframe->qgeneratebase = false;
3773 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);
3774 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);
3775 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);
3779 skinframe->qgeneratemerged = false;
3780 if (skinframe->hasalpha) // fence textures
3781 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);
3783 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);
3786 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3788 Mem_Free(skinframe->qpixels);
3789 skinframe->qpixels = NULL;
3793 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)
3796 skinframe_t *skinframe;
3799 if (cls.state == ca_dedicated)
3802 // if already loaded just return it, otherwise make a new skinframe
3803 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3804 if (skinframe->base)
3806 textureflags &= ~TEXF_FORCE_RELOAD;
3808 skinframe->stain = NULL;
3809 skinframe->merged = NULL;
3810 skinframe->base = NULL;
3811 skinframe->pants = NULL;
3812 skinframe->shirt = NULL;
3813 skinframe->nmap = NULL;
3814 skinframe->gloss = NULL;
3815 skinframe->glow = NULL;
3816 skinframe->fog = NULL;
3817 skinframe->reflect = NULL;
3818 skinframe->hasalpha = false;
3820 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3824 if (developer_loading.integer)
3825 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3827 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3828 if (textureflags & TEXF_ALPHA)
3830 for (i = 0;i < width * height;i++)
3832 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3834 skinframe->hasalpha = true;
3838 if (r_loadfog && skinframe->hasalpha)
3839 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3842 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3843 //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]);
3848 skinframe_t *R_SkinFrame_LoadMissing(void)
3850 skinframe_t *skinframe;
3852 if (cls.state == ca_dedicated)
3855 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3856 skinframe->stain = NULL;
3857 skinframe->merged = NULL;
3858 skinframe->base = NULL;
3859 skinframe->pants = NULL;
3860 skinframe->shirt = NULL;
3861 skinframe->nmap = NULL;
3862 skinframe->gloss = NULL;
3863 skinframe->glow = NULL;
3864 skinframe->fog = NULL;
3865 skinframe->reflect = NULL;
3866 skinframe->hasalpha = false;
3868 skinframe->avgcolor[0] = rand() / RAND_MAX;
3869 skinframe->avgcolor[1] = rand() / RAND_MAX;
3870 skinframe->avgcolor[2] = rand() / RAND_MAX;
3871 skinframe->avgcolor[3] = 1;
3876 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3877 typedef struct suffixinfo_s
3880 qboolean flipx, flipy, flipdiagonal;
3883 static suffixinfo_t suffix[3][6] =
3886 {"px", false, false, false},
3887 {"nx", false, false, false},
3888 {"py", false, false, false},
3889 {"ny", false, false, false},
3890 {"pz", false, false, false},
3891 {"nz", false, false, false}
3894 {"posx", false, false, false},
3895 {"negx", false, false, false},
3896 {"posy", false, false, false},
3897 {"negy", false, false, false},
3898 {"posz", false, false, false},
3899 {"negz", false, false, false}
3902 {"rt", true, false, true},
3903 {"lf", false, true, true},
3904 {"ft", true, true, false},
3905 {"bk", false, false, false},
3906 {"up", true, false, true},
3907 {"dn", true, false, true}
3911 static int componentorder[4] = {0, 1, 2, 3};
3913 static rtexture_t *R_LoadCubemap(const char *basename)
3915 int i, j, cubemapsize;
3916 unsigned char *cubemappixels, *image_buffer;
3917 rtexture_t *cubemaptexture;
3919 // must start 0 so the first loadimagepixels has no requested width/height
3921 cubemappixels = NULL;
3922 cubemaptexture = NULL;
3923 // keep trying different suffix groups (posx, px, rt) until one loads
3924 for (j = 0;j < 3 && !cubemappixels;j++)
3926 // load the 6 images in the suffix group
3927 for (i = 0;i < 6;i++)
3929 // generate an image name based on the base and and suffix
3930 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3932 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3934 // an image loaded, make sure width and height are equal
3935 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3937 // if this is the first image to load successfully, allocate the cubemap memory
3938 if (!cubemappixels && image_width >= 1)
3940 cubemapsize = image_width;
3941 // note this clears to black, so unavailable sides are black
3942 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3944 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3946 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);
3949 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3951 Mem_Free(image_buffer);
3955 // if a cubemap loaded, upload it
3958 if (developer_loading.integer)
3959 Con_Printf("loading cubemap \"%s\"\n", basename);
3961 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);
3962 Mem_Free(cubemappixels);
3966 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3967 if (developer_loading.integer)
3969 Con_Printf("(tried tried images ");
3970 for (j = 0;j < 3;j++)
3971 for (i = 0;i < 6;i++)
3972 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3973 Con_Print(" and was unable to find any of them).\n");
3976 return cubemaptexture;
3979 rtexture_t *R_GetCubemap(const char *basename)
3982 for (i = 0;i < r_texture_numcubemaps;i++)
3983 if (r_texture_cubemaps[i] != NULL)
3984 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3985 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3986 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3987 return r_texture_whitecube;
3988 r_texture_numcubemaps++;
3989 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3990 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3991 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3992 return r_texture_cubemaps[i]->texture;
3995 static void R_Main_FreeViewCache(void)
3997 if (r_refdef.viewcache.entityvisible)
3998 Mem_Free(r_refdef.viewcache.entityvisible);
3999 if (r_refdef.viewcache.world_pvsbits)
4000 Mem_Free(r_refdef.viewcache.world_pvsbits);
4001 if (r_refdef.viewcache.world_leafvisible)
4002 Mem_Free(r_refdef.viewcache.world_leafvisible);
4003 if (r_refdef.viewcache.world_surfacevisible)
4004 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4005 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4008 static void R_Main_ResizeViewCache(void)
4010 int numentities = r_refdef.scene.numentities;
4011 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4012 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4013 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4014 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4015 if (r_refdef.viewcache.maxentities < numentities)
4017 r_refdef.viewcache.maxentities = numentities;
4018 if (r_refdef.viewcache.entityvisible)
4019 Mem_Free(r_refdef.viewcache.entityvisible);
4020 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4022 if (r_refdef.viewcache.world_numclusters != numclusters)
4024 r_refdef.viewcache.world_numclusters = numclusters;
4025 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4026 if (r_refdef.viewcache.world_pvsbits)
4027 Mem_Free(r_refdef.viewcache.world_pvsbits);
4028 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4030 if (r_refdef.viewcache.world_numleafs != numleafs)
4032 r_refdef.viewcache.world_numleafs = numleafs;
4033 if (r_refdef.viewcache.world_leafvisible)
4034 Mem_Free(r_refdef.viewcache.world_leafvisible);
4035 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4037 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4039 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4040 if (r_refdef.viewcache.world_surfacevisible)
4041 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4042 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4046 extern rtexture_t *loadingscreentexture;
4047 static void gl_main_start(void)
4049 loadingscreentexture = NULL;
4050 r_texture_blanknormalmap = NULL;
4051 r_texture_white = NULL;
4052 r_texture_grey128 = NULL;
4053 r_texture_black = NULL;
4054 r_texture_whitecube = NULL;
4055 r_texture_normalizationcube = NULL;
4056 r_texture_fogattenuation = NULL;
4057 r_texture_fogheighttexture = NULL;
4058 r_texture_gammaramps = NULL;
4059 r_texture_numcubemaps = 0;
4060 r_uniformbufferalignment = 32;
4062 r_loaddds = r_texture_dds_load.integer != 0;
4063 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4065 switch(vid.renderpath)
4067 case RENDERPATH_GL20:
4068 case RENDERPATH_D3D9:
4069 case RENDERPATH_D3D10:
4070 case RENDERPATH_D3D11:
4071 case RENDERPATH_SOFT:
4072 case RENDERPATH_GLES2:
4073 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4074 Cvar_SetValueQuick(&gl_combine, 1);
4075 Cvar_SetValueQuick(&r_glsl, 1);
4076 r_loadnormalmap = true;
4079 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4080 if (vid.support.arb_uniform_buffer_object)
4081 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4084 case RENDERPATH_GL13:
4085 case RENDERPATH_GLES1:
4086 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4087 Cvar_SetValueQuick(&gl_combine, 1);
4088 Cvar_SetValueQuick(&r_glsl, 0);
4089 r_loadnormalmap = false;
4090 r_loadgloss = false;
4093 case RENDERPATH_GL11:
4094 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4095 Cvar_SetValueQuick(&gl_combine, 0);
4096 Cvar_SetValueQuick(&r_glsl, 0);
4097 r_loadnormalmap = false;
4098 r_loadgloss = false;
4104 R_FrameData_Reset();
4105 R_BufferData_Reset();
4109 memset(r_queries, 0, sizeof(r_queries));
4111 r_qwskincache = NULL;
4112 r_qwskincache_size = 0;
4114 // due to caching of texture_t references, the collision cache must be reset
4115 Collision_Cache_Reset(true);
4117 // set up r_skinframe loading system for textures
4118 memset(&r_skinframe, 0, sizeof(r_skinframe));
4119 r_skinframe.loadsequence = 1;
4120 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4122 r_main_texturepool = R_AllocTexturePool();
4123 R_BuildBlankTextures();
4125 if (vid.support.arb_texture_cube_map)
4128 R_BuildNormalizationCube();
4130 r_texture_fogattenuation = NULL;
4131 r_texture_fogheighttexture = NULL;
4132 r_texture_gammaramps = NULL;
4133 //r_texture_fogintensity = NULL;
4134 memset(&r_fb, 0, sizeof(r_fb));
4135 r_glsl_permutation = NULL;
4136 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4137 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4139 r_hlsl_permutation = NULL;
4140 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4141 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4143 memset(&r_svbsp, 0, sizeof (r_svbsp));
4145 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4146 r_texture_numcubemaps = 0;
4148 r_refdef.fogmasktable_density = 0;
4151 // For Steelstorm Android
4152 // FIXME CACHE the program and reload
4153 // FIXME see possible combinations for SS:BR android
4154 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4155 R_SetupShader_SetPermutationGLSL(0, 12);
4156 R_SetupShader_SetPermutationGLSL(0, 13);
4157 R_SetupShader_SetPermutationGLSL(0, 8388621);
4158 R_SetupShader_SetPermutationGLSL(3, 0);
4159 R_SetupShader_SetPermutationGLSL(3, 2048);
4160 R_SetupShader_SetPermutationGLSL(5, 0);
4161 R_SetupShader_SetPermutationGLSL(5, 2);
4162 R_SetupShader_SetPermutationGLSL(5, 2048);
4163 R_SetupShader_SetPermutationGLSL(5, 8388608);
4164 R_SetupShader_SetPermutationGLSL(11, 1);
4165 R_SetupShader_SetPermutationGLSL(11, 2049);
4166 R_SetupShader_SetPermutationGLSL(11, 8193);
4167 R_SetupShader_SetPermutationGLSL(11, 10241);
4168 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4172 static void gl_main_shutdown(void)
4175 R_FrameData_Reset();
4176 R_BufferData_Reset();
4178 R_Main_FreeViewCache();
4180 switch(vid.renderpath)
4182 case RENDERPATH_GL11:
4183 case RENDERPATH_GL13:
4184 case RENDERPATH_GL20:
4185 case RENDERPATH_GLES1:
4186 case RENDERPATH_GLES2:
4187 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4189 qglDeleteQueriesARB(r_maxqueries, r_queries);
4192 case RENDERPATH_D3D9:
4193 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4195 case RENDERPATH_D3D10:
4196 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4198 case RENDERPATH_D3D11:
4199 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4201 case RENDERPATH_SOFT:
4207 memset(r_queries, 0, sizeof(r_queries));
4209 r_qwskincache = NULL;
4210 r_qwskincache_size = 0;
4212 // clear out the r_skinframe state
4213 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4214 memset(&r_skinframe, 0, sizeof(r_skinframe));
4217 Mem_Free(r_svbsp.nodes);
4218 memset(&r_svbsp, 0, sizeof (r_svbsp));
4219 R_FreeTexturePool(&r_main_texturepool);
4220 loadingscreentexture = NULL;
4221 r_texture_blanknormalmap = NULL;
4222 r_texture_white = NULL;
4223 r_texture_grey128 = NULL;
4224 r_texture_black = NULL;
4225 r_texture_whitecube = NULL;
4226 r_texture_normalizationcube = NULL;
4227 r_texture_fogattenuation = NULL;
4228 r_texture_fogheighttexture = NULL;
4229 r_texture_gammaramps = NULL;
4230 r_texture_numcubemaps = 0;
4231 //r_texture_fogintensity = NULL;
4232 memset(&r_fb, 0, sizeof(r_fb));
4235 r_glsl_permutation = NULL;
4236 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4237 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4239 r_hlsl_permutation = NULL;
4240 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4241 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4245 static void gl_main_newmap(void)
4247 // FIXME: move this code to client
4248 char *entities, entname[MAX_QPATH];
4250 Mem_Free(r_qwskincache);
4251 r_qwskincache = NULL;
4252 r_qwskincache_size = 0;
4255 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4256 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4258 CL_ParseEntityLump(entities);
4262 if (cl.worldmodel->brush.entities)
4263 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4265 R_Main_FreeViewCache();
4267 R_FrameData_Reset();
4268 R_BufferData_Reset();
4271 void GL_Main_Init(void)
4274 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4275 R_InitShaderModeInfo();
4277 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4278 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4279 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4280 if (gamemode == GAME_NEHAHRA)
4282 Cvar_RegisterVariable (&gl_fogenable);
4283 Cvar_RegisterVariable (&gl_fogdensity);
4284 Cvar_RegisterVariable (&gl_fogred);
4285 Cvar_RegisterVariable (&gl_foggreen);
4286 Cvar_RegisterVariable (&gl_fogblue);
4287 Cvar_RegisterVariable (&gl_fogstart);
4288 Cvar_RegisterVariable (&gl_fogend);
4289 Cvar_RegisterVariable (&gl_skyclip);
4291 Cvar_RegisterVariable(&r_motionblur);
4292 Cvar_RegisterVariable(&r_damageblur);
4293 Cvar_RegisterVariable(&r_motionblur_averaging);
4294 Cvar_RegisterVariable(&r_motionblur_randomize);
4295 Cvar_RegisterVariable(&r_motionblur_minblur);
4296 Cvar_RegisterVariable(&r_motionblur_maxblur);
4297 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4298 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4299 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4300 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4301 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4302 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4303 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4304 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4305 Cvar_RegisterVariable(&r_equalize_entities_by);
4306 Cvar_RegisterVariable(&r_equalize_entities_to);
4307 Cvar_RegisterVariable(&r_depthfirst);
4308 Cvar_RegisterVariable(&r_useinfinitefarclip);
4309 Cvar_RegisterVariable(&r_farclip_base);
4310 Cvar_RegisterVariable(&r_farclip_world);
4311 Cvar_RegisterVariable(&r_nearclip);
4312 Cvar_RegisterVariable(&r_deformvertexes);
4313 Cvar_RegisterVariable(&r_transparent);
4314 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4315 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4316 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4317 Cvar_RegisterVariable(&r_showoverdraw);
4318 Cvar_RegisterVariable(&r_showbboxes);
4319 Cvar_RegisterVariable(&r_showsurfaces);
4320 Cvar_RegisterVariable(&r_showtris);
4321 Cvar_RegisterVariable(&r_shownormals);
4322 Cvar_RegisterVariable(&r_showlighting);
4323 Cvar_RegisterVariable(&r_showshadowvolumes);
4324 Cvar_RegisterVariable(&r_showcollisionbrushes);
4325 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4326 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4327 Cvar_RegisterVariable(&r_showdisabledepthtest);
4328 Cvar_RegisterVariable(&r_drawportals);
4329 Cvar_RegisterVariable(&r_drawentities);
4330 Cvar_RegisterVariable(&r_draw2d);
4331 Cvar_RegisterVariable(&r_drawworld);
4332 Cvar_RegisterVariable(&r_cullentities_trace);
4333 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4334 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4335 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4336 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4337 Cvar_RegisterVariable(&r_sortentities);
4338 Cvar_RegisterVariable(&r_drawviewmodel);
4339 Cvar_RegisterVariable(&r_drawexteriormodel);
4340 Cvar_RegisterVariable(&r_speeds);
4341 Cvar_RegisterVariable(&r_fullbrights);
4342 Cvar_RegisterVariable(&r_wateralpha);
4343 Cvar_RegisterVariable(&r_dynamic);
4344 Cvar_RegisterVariable(&r_fakelight);
4345 Cvar_RegisterVariable(&r_fakelight_intensity);
4346 Cvar_RegisterVariable(&r_fullbright);
4347 Cvar_RegisterVariable(&r_shadows);
4348 Cvar_RegisterVariable(&r_shadows_darken);
4349 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4350 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4351 Cvar_RegisterVariable(&r_shadows_throwdistance);
4352 Cvar_RegisterVariable(&r_shadows_throwdirection);
4353 Cvar_RegisterVariable(&r_shadows_focus);
4354 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4355 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4356 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4357 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4358 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4359 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4360 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4361 Cvar_RegisterVariable(&r_fog_exp2);
4362 Cvar_RegisterVariable(&r_fog_clear);
4363 Cvar_RegisterVariable(&r_drawfog);
4364 Cvar_RegisterVariable(&r_transparentdepthmasking);
4365 Cvar_RegisterVariable(&r_transparent_sortmindist);
4366 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4367 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4368 Cvar_RegisterVariable(&r_texture_dds_load);
4369 Cvar_RegisterVariable(&r_texture_dds_save);
4370 Cvar_RegisterVariable(&r_textureunits);
4371 Cvar_RegisterVariable(&gl_combine);
4372 Cvar_RegisterVariable(&r_usedepthtextures);
4373 Cvar_RegisterVariable(&r_viewfbo);
4374 Cvar_RegisterVariable(&r_viewscale);
4375 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4376 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4377 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4378 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4379 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4380 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4381 Cvar_RegisterVariable(&r_glsl);
4382 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4383 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4384 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4385 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4386 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4387 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4388 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4389 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4390 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4391 Cvar_RegisterVariable(&r_glsl_postprocess);
4392 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4393 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4394 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4395 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4396 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4397 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4398 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4399 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4400 Cvar_RegisterVariable(&r_celshading);
4401 Cvar_RegisterVariable(&r_celoutlines);
4403 Cvar_RegisterVariable(&r_water);
4404 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4405 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4406 Cvar_RegisterVariable(&r_water_clippingplanebias);
4407 Cvar_RegisterVariable(&r_water_refractdistort);
4408 Cvar_RegisterVariable(&r_water_reflectdistort);
4409 Cvar_RegisterVariable(&r_water_scissormode);
4410 Cvar_RegisterVariable(&r_water_lowquality);
4411 Cvar_RegisterVariable(&r_water_hideplayer);
4412 Cvar_RegisterVariable(&r_water_fbo);
4414 Cvar_RegisterVariable(&r_lerpsprites);
4415 Cvar_RegisterVariable(&r_lerpmodels);
4416 Cvar_RegisterVariable(&r_lerplightstyles);
4417 Cvar_RegisterVariable(&r_waterscroll);
4418 Cvar_RegisterVariable(&r_bloom);
4419 Cvar_RegisterVariable(&r_bloom_colorscale);
4420 Cvar_RegisterVariable(&r_bloom_brighten);
4421 Cvar_RegisterVariable(&r_bloom_blur);
4422 Cvar_RegisterVariable(&r_bloom_resolution);
4423 Cvar_RegisterVariable(&r_bloom_colorexponent);
4424 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4425 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4426 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4427 Cvar_RegisterVariable(&r_hdr_glowintensity);
4428 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4429 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4430 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4431 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4432 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4433 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4434 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4435 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4436 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4437 Cvar_RegisterVariable(&developer_texturelogging);
4438 Cvar_RegisterVariable(&gl_lightmaps);
4439 Cvar_RegisterVariable(&r_test);
4440 Cvar_RegisterVariable(&r_batch_multidraw);
4441 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4442 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4443 Cvar_RegisterVariable(&r_glsl_skeletal);
4444 Cvar_RegisterVariable(&r_glsl_saturation);
4445 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4446 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4447 Cvar_RegisterVariable(&r_framedatasize);
4448 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4449 Cvar_RegisterVariable(&r_buffermegs[i]);
4450 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4451 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4452 Cvar_SetValue("r_fullbrights", 0);
4453 #ifdef DP_MOBILETOUCH
4454 // GLES devices have terrible depth precision in general, so...
4455 Cvar_SetValueQuick(&r_nearclip, 4);
4456 Cvar_SetValueQuick(&r_farclip_base, 4096);
4457 Cvar_SetValueQuick(&r_farclip_world, 0);
4458 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4460 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4463 void Render_Init(void)
4476 R_LightningBeams_Init();
4486 extern char *ENGINE_EXTENSIONS;
4489 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4490 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4491 gl_version = (const char *)qglGetString(GL_VERSION);
4492 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4496 if (!gl_platformextensions)
4497 gl_platformextensions = "";
4499 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4500 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4501 Con_Printf("GL_VERSION: %s\n", gl_version);
4502 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4503 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4505 VID_CheckExtensions();
4507 // LordHavoc: report supported extensions
4509 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4511 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4514 // clear to black (loading plaque will be seen over this)
4515 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4519 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4523 if (r_trippy.integer)
4525 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4527 p = r_refdef.view.frustum + i;
4532 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4536 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4540 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4544 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4548 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4552 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4556 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4560 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4568 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4572 if (r_trippy.integer)
4574 for (i = 0;i < numplanes;i++)
4581 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4585 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4589 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4593 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4597 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4601 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4605 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4609 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4617 //==================================================================================
4619 // LordHavoc: this stores temporary data used within the same frame
4621 typedef struct r_framedata_mem_s
4623 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4624 size_t size; // how much usable space
4625 size_t current; // how much space in use
4626 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4627 size_t wantedsize; // how much space was allocated
4628 unsigned char *data; // start of real data (16byte aligned)
4632 static r_framedata_mem_t *r_framedata_mem;
4634 void R_FrameData_Reset(void)
4636 while (r_framedata_mem)
4638 r_framedata_mem_t *next = r_framedata_mem->purge;
4639 Mem_Free(r_framedata_mem);
4640 r_framedata_mem = next;
4644 static void R_FrameData_Resize(qboolean mustgrow)
4647 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4648 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4649 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4651 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4652 newmem->wantedsize = wantedsize;
4653 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4654 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4655 newmem->current = 0;
4657 newmem->purge = r_framedata_mem;
4658 r_framedata_mem = newmem;
4662 void R_FrameData_NewFrame(void)
4664 R_FrameData_Resize(false);
4665 if (!r_framedata_mem)
4667 // if we ran out of space on the last frame, free the old memory now
4668 while (r_framedata_mem->purge)
4670 // repeatedly remove the second item in the list, leaving only head
4671 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4672 Mem_Free(r_framedata_mem->purge);
4673 r_framedata_mem->purge = next;
4675 // reset the current mem pointer
4676 r_framedata_mem->current = 0;
4677 r_framedata_mem->mark = 0;
4680 void *R_FrameData_Alloc(size_t size)
4685 // align to 16 byte boundary - the data pointer is already aligned, so we
4686 // only need to ensure the size of every allocation is also aligned
4687 size = (size + 15) & ~15;
4689 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4691 // emergency - we ran out of space, allocate more memory
4692 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4693 newvalue = r_framedatasize.value * 2.0f;
4694 // 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
4695 if (sizeof(size_t) >= 8)
4696 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4698 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4699 // this might not be a growing it, but we'll allocate another buffer every time
4700 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4701 R_FrameData_Resize(true);
4704 data = r_framedata_mem->data + r_framedata_mem->current;
4705 r_framedata_mem->current += size;
4707 // count the usage for stats
4708 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4709 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4711 return (void *)data;
4714 void *R_FrameData_Store(size_t size, void *data)
4716 void *d = R_FrameData_Alloc(size);
4718 memcpy(d, data, size);
4722 void R_FrameData_SetMark(void)
4724 if (!r_framedata_mem)
4726 r_framedata_mem->mark = r_framedata_mem->current;
4729 void R_FrameData_ReturnToMark(void)
4731 if (!r_framedata_mem)
4733 r_framedata_mem->current = r_framedata_mem->mark;
4736 //==================================================================================
4738 // avoid reusing the same buffer objects on consecutive frames
4739 #define R_BUFFERDATA_CYCLE 3
4741 typedef struct r_bufferdata_buffer_s
4743 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4744 size_t size; // how much usable space
4745 size_t current; // how much space in use
4746 r_meshbuffer_t *buffer; // the buffer itself
4748 r_bufferdata_buffer_t;
4750 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4751 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4753 /// frees all dynamic buffers
4754 void R_BufferData_Reset(void)
4757 r_bufferdata_buffer_t **p, *mem;
4758 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4760 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4763 p = &r_bufferdata_buffer[cycle][type];
4769 R_Mesh_DestroyMeshBuffer(mem->buffer);
4776 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4777 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4779 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4781 float newvalue = r_buffermegs[type].value;
4783 // increase the cvar if we have to (but only if we already have a mem)
4784 if (mustgrow && mem)
4786 newvalue = bound(0.25f, newvalue, 256.0f);
4787 while (newvalue * 1024*1024 < minsize)
4790 // clamp the cvar to valid range
4791 newvalue = bound(0.25f, newvalue, 256.0f);
4792 if (r_buffermegs[type].value != newvalue)
4793 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4795 // calculate size in bytes
4796 size = (size_t)(newvalue * 1024*1024);
4797 size = bound(131072, size, 256*1024*1024);
4799 // allocate a new buffer if the size is different (purge old one later)
4800 // or if we were told we must grow the buffer
4801 if (!mem || mem->size != size || mustgrow)
4803 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4806 if (type == R_BUFFERDATA_VERTEX)
4807 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4808 else if (type == R_BUFFERDATA_INDEX16)
4809 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4810 else if (type == R_BUFFERDATA_INDEX32)
4811 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4812 else if (type == R_BUFFERDATA_UNIFORM)
4813 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4814 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4815 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4819 void R_BufferData_NewFrame(void)
4822 r_bufferdata_buffer_t **p, *mem;
4823 // cycle to the next frame's buffers
4824 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4825 // if we ran out of space on the last time we used these buffers, free the old memory now
4826 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4828 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4830 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4831 // free all but the head buffer, this is how we recycle obsolete
4832 // buffers after they are no longer in use
4833 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4839 R_Mesh_DestroyMeshBuffer(mem->buffer);
4842 // reset the current offset
4843 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4848 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4850 r_bufferdata_buffer_t *mem;
4854 *returnbufferoffset = 0;
4856 // align size to a byte boundary appropriate for the buffer type, this
4857 // makes all allocations have aligned start offsets
4858 if (type == R_BUFFERDATA_UNIFORM)
4859 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4861 padsize = (datasize + 15) & ~15;
4863 // if we ran out of space in this buffer we must allocate a new one
4864 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)
4865 R_BufferData_Resize(type, true, padsize);
4867 // if the resize did not give us enough memory, fail
4868 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)
4869 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4871 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4872 offset = (int)mem->current;
4873 mem->current += padsize;
4875 // upload the data to the buffer at the chosen offset
4877 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4878 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4880 // count the usage for stats
4881 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4882 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4884 // return the buffer offset
4885 *returnbufferoffset = offset;
4890 //==================================================================================
4892 // LordHavoc: animcache originally written by Echon, rewritten since then
4895 * Animation cache prevents re-generating mesh data for an animated model
4896 * multiple times in one frame for lighting, shadowing, reflections, etc.
4899 void R_AnimCache_Free(void)
4903 void R_AnimCache_ClearCache(void)
4906 entity_render_t *ent;
4908 for (i = 0;i < r_refdef.scene.numentities;i++)
4910 ent = r_refdef.scene.entities[i];
4911 ent->animcache_vertex3f = NULL;
4912 ent->animcache_vertex3f_vertexbuffer = NULL;
4913 ent->animcache_vertex3f_bufferoffset = 0;
4914 ent->animcache_normal3f = NULL;
4915 ent->animcache_normal3f_vertexbuffer = NULL;
4916 ent->animcache_normal3f_bufferoffset = 0;
4917 ent->animcache_svector3f = NULL;
4918 ent->animcache_svector3f_vertexbuffer = NULL;
4919 ent->animcache_svector3f_bufferoffset = 0;
4920 ent->animcache_tvector3f = NULL;
4921 ent->animcache_tvector3f_vertexbuffer = NULL;
4922 ent->animcache_tvector3f_bufferoffset = 0;
4923 ent->animcache_vertexmesh = NULL;
4924 ent->animcache_vertexmesh_vertexbuffer = NULL;
4925 ent->animcache_vertexmesh_bufferoffset = 0;
4926 ent->animcache_skeletaltransform3x4 = NULL;
4927 ent->animcache_skeletaltransform3x4buffer = NULL;
4928 ent->animcache_skeletaltransform3x4offset = 0;
4929 ent->animcache_skeletaltransform3x4size = 0;
4933 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4937 // check if we need the meshbuffers
4938 if (!vid.useinterleavedarrays)
4941 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4942 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4943 // TODO: upload vertexbuffer?
4944 if (ent->animcache_vertexmesh)
4946 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4947 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4948 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4949 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4950 for (i = 0;i < numvertices;i++)
4951 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4952 if (ent->animcache_svector3f)
4953 for (i = 0;i < numvertices;i++)
4954 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4955 if (ent->animcache_tvector3f)
4956 for (i = 0;i < numvertices;i++)
4957 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4958 if (ent->animcache_normal3f)
4959 for (i = 0;i < numvertices;i++)
4960 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4964 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4966 dp_model_t *model = ent->model;
4969 // see if this ent is worth caching
4970 if (!model || !model->Draw || !model->AnimateVertices)
4972 // nothing to cache if it contains no animations and has no skeleton
4973 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4975 // see if it is already cached for gpuskeletal
4976 if (ent->animcache_skeletaltransform3x4)
4978 // see if it is already cached as a mesh
4979 if (ent->animcache_vertex3f)
4981 // check if we need to add normals or tangents
4982 if (ent->animcache_normal3f)
4983 wantnormals = false;
4984 if (ent->animcache_svector3f)
4985 wanttangents = false;
4986 if (!wantnormals && !wanttangents)
4990 // check which kind of cache we need to generate
4991 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4993 // cache the skeleton so the vertex shader can use it
4994 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4995 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4996 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4997 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4998 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4999 // note: this can fail if the buffer is at the grow limit
5000 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5001 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5003 else if (ent->animcache_vertex3f)
5005 // mesh was already cached but we may need to add normals/tangents
5006 // (this only happens with multiple views, reflections, cameras, etc)
5007 if (wantnormals || wanttangents)
5009 numvertices = model->surfmesh.num_vertices;
5011 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5014 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5015 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5017 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5018 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5019 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5020 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5021 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5026 // generate mesh cache
5027 numvertices = model->surfmesh.num_vertices;
5028 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5030 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5033 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5034 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5036 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5037 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5038 if (wantnormals || wanttangents)
5040 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5041 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5042 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5044 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5045 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5046 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5051 void R_AnimCache_CacheVisibleEntities(void)
5054 qboolean wantnormals = true;
5055 qboolean wanttangents = !r_showsurfaces.integer;
5057 switch(vid.renderpath)
5059 case RENDERPATH_GL20:
5060 case RENDERPATH_D3D9:
5061 case RENDERPATH_D3D10:
5062 case RENDERPATH_D3D11:
5063 case RENDERPATH_GLES2:
5065 case RENDERPATH_GL11:
5066 case RENDERPATH_GL13:
5067 case RENDERPATH_GLES1:
5068 wanttangents = false;
5070 case RENDERPATH_SOFT:
5074 if (r_shownormals.integer)
5075 wanttangents = wantnormals = true;
5077 // TODO: thread this
5078 // NOTE: R_PrepareRTLights() also caches entities
5080 for (i = 0;i < r_refdef.scene.numentities;i++)
5081 if (r_refdef.viewcache.entityvisible[i])
5082 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5085 //==================================================================================
5087 extern cvar_t r_overheadsprites_pushback;
5089 static void R_View_UpdateEntityLighting (void)
5092 entity_render_t *ent;
5093 vec3_t tempdiffusenormal, avg;
5094 vec_t f, fa, fd, fdd;
5095 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5097 for (i = 0;i < r_refdef.scene.numentities;i++)
5099 ent = r_refdef.scene.entities[i];
5101 // skip unseen models
5102 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5106 if (ent->model && ent->model == cl.worldmodel)
5108 // TODO: use modellight for r_ambient settings on world?
5109 VectorSet(ent->modellight_ambient, 0, 0, 0);
5110 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5111 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5115 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5117 // aleady updated by CSQC
5118 // TODO: force modellight on BSP models in this case?
5119 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5123 // fetch the lighting from the worldmodel data
5124 VectorClear(ent->modellight_ambient);
5125 VectorClear(ent->modellight_diffuse);
5126 VectorClear(tempdiffusenormal);
5127 if (ent->flags & RENDER_LIGHT)
5130 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5132 // complete lightning for lit sprites
5133 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5134 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5136 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5137 org[2] = org[2] + r_overheadsprites_pushback.value;
5138 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5141 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5143 if(ent->flags & RENDER_EQUALIZE)
5145 // first fix up ambient lighting...
5146 if(r_equalize_entities_minambient.value > 0)
5148 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5151 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5152 if(fa < r_equalize_entities_minambient.value * fd)
5155 // fa'/fd' = minambient
5156 // fa'+0.25*fd' = fa+0.25*fd
5158 // fa' = fd' * minambient
5159 // fd'*(0.25+minambient) = fa+0.25*fd
5161 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5162 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5164 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5165 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
5166 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5167 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5172 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5174 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5175 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5179 // adjust brightness and saturation to target
5180 avg[0] = avg[1] = avg[2] = fa / f;
5181 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5182 avg[0] = avg[1] = avg[2] = fd / f;
5183 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5189 VectorSet(ent->modellight_ambient, 1, 1, 1);
5192 // move the light direction into modelspace coordinates for lighting code
5193 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5194 if(VectorLength2(ent->modellight_lightdir) == 0)
5195 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5196 VectorNormalize(ent->modellight_lightdir);
5200 #define MAX_LINEOFSIGHTTRACES 64
5202 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5205 vec3_t boxmins, boxmaxs;
5208 dp_model_t *model = r_refdef.scene.worldmodel;
5210 if (!model || !model->brush.TraceLineOfSight)
5213 // expand the box a little
5214 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5215 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5216 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5217 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5218 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5219 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5221 // return true if eye is inside enlarged box
5222 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5226 VectorCopy(eye, start);
5227 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5228 if (model->brush.TraceLineOfSight(model, start, end))
5231 // try various random positions
5232 for (i = 0;i < numsamples;i++)
5234 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5235 if (model->brush.TraceLineOfSight(model, start, end))
5243 static void R_View_UpdateEntityVisible (void)
5248 entity_render_t *ent;
5250 if (r_refdef.envmap || r_fb.water.hideplayer)
5251 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5252 else if (chase_active.integer || r_fb.water.renderingscene)
5253 renderimask = RENDER_VIEWMODEL;
5255 renderimask = RENDER_EXTERIORMODEL;
5256 if (!r_drawviewmodel.integer)
5257 renderimask |= RENDER_VIEWMODEL;
5258 if (!r_drawexteriormodel.integer)
5259 renderimask |= RENDER_EXTERIORMODEL;
5260 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5261 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5263 // worldmodel can check visibility
5264 for (i = 0;i < r_refdef.scene.numentities;i++)
5266 ent = r_refdef.scene.entities[i];
5267 if (!(ent->flags & renderimask))
5268 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)))
5269 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))
5270 r_refdef.viewcache.entityvisible[i] = true;
5275 // no worldmodel or it can't check visibility
5276 for (i = 0;i < r_refdef.scene.numentities;i++)
5278 ent = r_refdef.scene.entities[i];
5279 if (!(ent->flags & renderimask))
5280 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)))
5281 r_refdef.viewcache.entityvisible[i] = true;
5284 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5285 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5287 for (i = 0;i < r_refdef.scene.numentities;i++)
5289 if (!r_refdef.viewcache.entityvisible[i])
5291 ent = r_refdef.scene.entities[i];
5292 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5294 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5296 continue; // temp entities do pvs only
5297 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5298 ent->last_trace_visibility = realtime;
5299 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5300 r_refdef.viewcache.entityvisible[i] = 0;
5306 /// only used if skyrendermasked, and normally returns false
5307 static int R_DrawBrushModelsSky (void)
5310 entity_render_t *ent;
5313 for (i = 0;i < r_refdef.scene.numentities;i++)
5315 if (!r_refdef.viewcache.entityvisible[i])
5317 ent = r_refdef.scene.entities[i];
5318 if (!ent->model || !ent->model->DrawSky)
5320 ent->model->DrawSky(ent);
5326 static void R_DrawNoModel(entity_render_t *ent);
5327 static void R_DrawModels(void)
5330 entity_render_t *ent;
5332 for (i = 0;i < r_refdef.scene.numentities;i++)
5334 if (!r_refdef.viewcache.entityvisible[i])
5336 ent = r_refdef.scene.entities[i];
5337 r_refdef.stats[r_stat_entities]++;
5339 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5342 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5343 Con_Printf("R_DrawModels\n");
5344 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]);
5345 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);
5346 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);
5349 if (ent->model && ent->model->Draw != NULL)
5350 ent->model->Draw(ent);
5356 static void R_DrawModelsDepth(void)
5359 entity_render_t *ent;
5361 for (i = 0;i < r_refdef.scene.numentities;i++)
5363 if (!r_refdef.viewcache.entityvisible[i])
5365 ent = r_refdef.scene.entities[i];
5366 if (ent->model && ent->model->DrawDepth != NULL)
5367 ent->model->DrawDepth(ent);
5371 static void R_DrawModelsDebug(void)
5374 entity_render_t *ent;
5376 for (i = 0;i < r_refdef.scene.numentities;i++)
5378 if (!r_refdef.viewcache.entityvisible[i])
5380 ent = r_refdef.scene.entities[i];
5381 if (ent->model && ent->model->DrawDebug != NULL)
5382 ent->model->DrawDebug(ent);
5386 static void R_DrawModelsAddWaterPlanes(void)
5389 entity_render_t *ent;
5391 for (i = 0;i < r_refdef.scene.numentities;i++)
5393 if (!r_refdef.viewcache.entityvisible[i])
5395 ent = r_refdef.scene.entities[i];
5396 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5397 ent->model->DrawAddWaterPlanes(ent);
5401 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}};
5403 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5405 if (r_hdr_irisadaptation.integer)
5410 vec3_t diffusenormal;
5412 vec_t brightness = 0.0f;
5417 VectorCopy(r_refdef.view.forward, forward);
5418 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5420 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5421 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5422 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5423 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5424 d = DotProduct(forward, diffusenormal);
5425 brightness += VectorLength(ambient);
5427 brightness += d * VectorLength(diffuse);
5429 brightness *= 1.0f / c;
5430 brightness += 0.00001f; // make sure it's never zero
5431 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5432 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5433 current = r_hdr_irisadaptation_value.value;
5435 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5436 else if (current > goal)
5437 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5438 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5439 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5441 else if (r_hdr_irisadaptation_value.value != 1.0f)
5442 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5445 static void R_View_SetFrustum(const int *scissor)
5448 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5449 vec3_t forward, left, up, origin, v;
5453 // flipped x coordinates (because x points left here)
5454 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5455 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5457 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5458 switch(vid.renderpath)
5460 case RENDERPATH_D3D9:
5461 case RENDERPATH_D3D10:
5462 case RENDERPATH_D3D11:
5463 // non-flipped y coordinates
5464 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5465 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5467 case RENDERPATH_SOFT:
5468 case RENDERPATH_GL11:
5469 case RENDERPATH_GL13:
5470 case RENDERPATH_GL20:
5471 case RENDERPATH_GLES1:
5472 case RENDERPATH_GLES2:
5473 // non-flipped y coordinates
5474 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5475 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5480 // we can't trust r_refdef.view.forward and friends in reflected scenes
5481 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5484 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5485 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5486 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5487 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5488 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5489 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5490 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5491 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5492 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5493 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5494 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5495 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5499 zNear = r_refdef.nearclip;
5500 nudge = 1.0 - 1.0 / (1<<23);
5501 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5502 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5503 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5504 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5505 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5506 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5507 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5508 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5514 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5515 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5516 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5517 r_refdef.view.frustum[0].dist = m[15] - m[12];
5519 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5520 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5521 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5522 r_refdef.view.frustum[1].dist = m[15] + m[12];
5524 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5525 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5526 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5527 r_refdef.view.frustum[2].dist = m[15] - m[13];
5529 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5530 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5531 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5532 r_refdef.view.frustum[3].dist = m[15] + m[13];
5534 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5535 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5536 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5537 r_refdef.view.frustum[4].dist = m[15] - m[14];
5539 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5540 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5541 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5542 r_refdef.view.frustum[5].dist = m[15] + m[14];
5545 if (r_refdef.view.useperspective)
5547 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5548 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]);
5549 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]);
5550 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]);
5551 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]);
5553 // then the normals from the corners relative to origin
5554 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5555 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5556 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5557 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5559 // in a NORMAL view, forward cross left == up
5560 // in a REFLECTED view, forward cross left == down
5561 // so our cross products above need to be adjusted for a left handed coordinate system
5562 CrossProduct(forward, left, v);
5563 if(DotProduct(v, up) < 0)
5565 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5566 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5567 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5568 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5571 // Leaving those out was a mistake, those were in the old code, and they
5572 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5573 // I couldn't reproduce it after adding those normalizations. --blub
5574 VectorNormalize(r_refdef.view.frustum[0].normal);
5575 VectorNormalize(r_refdef.view.frustum[1].normal);
5576 VectorNormalize(r_refdef.view.frustum[2].normal);
5577 VectorNormalize(r_refdef.view.frustum[3].normal);
5579 // make the corners absolute
5580 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5581 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5582 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5583 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5586 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5588 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5589 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5590 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5591 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5592 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5596 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5597 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5598 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5599 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5600 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5601 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5602 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5603 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5604 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5605 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5607 r_refdef.view.numfrustumplanes = 5;
5609 if (r_refdef.view.useclipplane)
5611 r_refdef.view.numfrustumplanes = 6;
5612 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5615 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5616 PlaneClassify(r_refdef.view.frustum + i);
5618 // LordHavoc: note to all quake engine coders, Quake had a special case
5619 // for 90 degrees which assumed a square view (wrong), so I removed it,
5620 // Quake2 has it disabled as well.
5622 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5623 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5624 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5625 //PlaneClassify(&frustum[0]);
5627 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5628 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5629 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5630 //PlaneClassify(&frustum[1]);
5632 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5633 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5634 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5635 //PlaneClassify(&frustum[2]);
5637 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5638 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5639 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5640 //PlaneClassify(&frustum[3]);
5643 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5644 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5645 //PlaneClassify(&frustum[4]);
5648 static void R_View_UpdateWithScissor(const int *myscissor)
5650 R_Main_ResizeViewCache();
5651 R_View_SetFrustum(myscissor);
5652 R_View_WorldVisibility(r_refdef.view.useclipplane);
5653 R_View_UpdateEntityVisible();
5654 R_View_UpdateEntityLighting();
5657 static void R_View_Update(void)
5659 R_Main_ResizeViewCache();
5660 R_View_SetFrustum(NULL);
5661 R_View_WorldVisibility(r_refdef.view.useclipplane);
5662 R_View_UpdateEntityVisible();
5663 R_View_UpdateEntityLighting();
5666 float viewscalefpsadjusted = 1.0f;
5668 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5670 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5671 scale = bound(0.03125f, scale, 1.0f);
5672 *outwidth = (int)ceil(width * scale);
5673 *outheight = (int)ceil(height * scale);
5676 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5678 const float *customclipplane = NULL;
5680 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5681 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5683 // LordHavoc: couldn't figure out how to make this approach the
5684 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5685 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5686 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5687 dist = r_refdef.view.clipplane.dist;
5688 plane[0] = r_refdef.view.clipplane.normal[0];
5689 plane[1] = r_refdef.view.clipplane.normal[1];
5690 plane[2] = r_refdef.view.clipplane.normal[2];
5692 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5695 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5696 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5698 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5699 if (!r_refdef.view.useperspective)
5700 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -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);
5701 else if (vid.stencil && r_useinfinitefarclip.integer)
5702 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5704 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5705 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5706 R_SetViewport(&r_refdef.view.viewport);
5707 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5709 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5710 float screenplane[4];
5711 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5712 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5713 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5714 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5715 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5719 void R_EntityMatrix(const matrix4x4_t *matrix)
5721 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5723 gl_modelmatrixchanged = false;
5724 gl_modelmatrix = *matrix;
5725 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5726 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5727 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5728 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5730 switch(vid.renderpath)
5732 case RENDERPATH_D3D9:
5734 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5735 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5738 case RENDERPATH_D3D10:
5739 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5741 case RENDERPATH_D3D11:
5742 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5744 case RENDERPATH_GL11:
5745 case RENDERPATH_GL13:
5746 case RENDERPATH_GLES1:
5748 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5751 case RENDERPATH_SOFT:
5752 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5753 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5755 case RENDERPATH_GL20:
5756 case RENDERPATH_GLES2:
5757 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5758 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5764 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5766 r_viewport_t viewport;
5770 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5771 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
5772 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5773 R_SetViewport(&viewport);
5774 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5775 GL_Color(1, 1, 1, 1);
5776 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5777 GL_BlendFunc(GL_ONE, GL_ZERO);
5778 GL_ScissorTest(false);
5779 GL_DepthMask(false);
5780 GL_DepthRange(0, 1);
5781 GL_DepthTest(false);
5782 GL_DepthFunc(GL_LEQUAL);
5783 R_EntityMatrix(&identitymatrix);
5784 R_Mesh_ResetTextureState();
5785 GL_PolygonOffset(0, 0);
5786 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5787 switch(vid.renderpath)
5789 case RENDERPATH_GL11:
5790 case RENDERPATH_GL13:
5791 case RENDERPATH_GL20:
5792 case RENDERPATH_GLES1:
5793 case RENDERPATH_GLES2:
5794 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5796 case RENDERPATH_D3D9:
5797 case RENDERPATH_D3D10:
5798 case RENDERPATH_D3D11:
5799 case RENDERPATH_SOFT:
5802 GL_CullFace(GL_NONE);
5807 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5811 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5814 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5818 R_SetupView(true, fbo, depthtexture, colortexture);
5819 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5820 GL_Color(1, 1, 1, 1);
5821 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5822 GL_BlendFunc(GL_ONE, GL_ZERO);
5823 GL_ScissorTest(true);
5825 GL_DepthRange(0, 1);
5827 GL_DepthFunc(GL_LEQUAL);
5828 R_EntityMatrix(&identitymatrix);
5829 R_Mesh_ResetTextureState();
5830 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5831 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5832 switch(vid.renderpath)
5834 case RENDERPATH_GL11:
5835 case RENDERPATH_GL13:
5836 case RENDERPATH_GL20:
5837 case RENDERPATH_GLES1:
5838 case RENDERPATH_GLES2:
5839 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5841 case RENDERPATH_D3D9:
5842 case RENDERPATH_D3D10:
5843 case RENDERPATH_D3D11:
5844 case RENDERPATH_SOFT:
5847 GL_CullFace(r_refdef.view.cullface_back);
5852 R_RenderView_UpdateViewVectors
5855 void R_RenderView_UpdateViewVectors(void)
5857 // break apart the view matrix into vectors for various purposes
5858 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5859 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5860 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5861 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5862 // make an inverted copy of the view matrix for tracking sprites
5863 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5866 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5867 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5869 static void R_Water_StartFrame(void)
5872 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5873 r_waterstate_waterplane_t *p;
5874 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5876 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5879 switch(vid.renderpath)
5881 case RENDERPATH_GL20:
5882 case RENDERPATH_D3D9:
5883 case RENDERPATH_D3D10:
5884 case RENDERPATH_D3D11:
5885 case RENDERPATH_SOFT:
5886 case RENDERPATH_GLES2:
5888 case RENDERPATH_GL11:
5889 case RENDERPATH_GL13:
5890 case RENDERPATH_GLES1:
5894 // set waterwidth and waterheight to the water resolution that will be
5895 // used (often less than the screen resolution for faster rendering)
5896 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5898 // calculate desired texture sizes
5899 // can't use water if the card does not support the texture size
5900 if (!r_water.integer || r_showsurfaces.integer)
5901 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5902 else if (vid.support.arb_texture_non_power_of_two)
5904 texturewidth = waterwidth;
5905 textureheight = waterheight;
5906 camerawidth = waterwidth;
5907 cameraheight = waterheight;
5911 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5912 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5913 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5914 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5917 // allocate textures as needed
5918 if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5920 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5921 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5923 if (p->texture_refraction)
5924 R_FreeTexture(p->texture_refraction);
5925 p->texture_refraction = NULL;
5926 if (p->fbo_refraction)
5927 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5928 p->fbo_refraction = 0;
5929 if (p->texture_reflection)
5930 R_FreeTexture(p->texture_reflection);
5931 p->texture_reflection = NULL;
5932 if (p->fbo_reflection)
5933 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5934 p->fbo_reflection = 0;
5935 if (p->texture_camera)
5936 R_FreeTexture(p->texture_camera);
5937 p->texture_camera = NULL;
5939 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5942 memset(&r_fb.water, 0, sizeof(r_fb.water));
5943 r_fb.water.texturewidth = texturewidth;
5944 r_fb.water.textureheight = textureheight;
5945 r_fb.water.camerawidth = camerawidth;
5946 r_fb.water.cameraheight = cameraheight;
5949 if (r_fb.water.texturewidth)
5951 int scaledwidth, scaledheight;
5953 r_fb.water.enabled = true;
5955 // water resolution is usually reduced
5956 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5957 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5958 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5960 // set up variables that will be used in shader setup
5961 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5962 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5963 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5964 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5967 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5968 r_fb.water.numwaterplanes = 0;
5971 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5973 int planeindex, bestplaneindex, vertexindex;
5974 vec3_t mins, maxs, normal, center, v, n;
5975 vec_t planescore, bestplanescore;
5977 r_waterstate_waterplane_t *p;
5978 texture_t *t = R_GetCurrentTexture(surface->texture);
5980 rsurface.texture = t;
5981 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5982 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5983 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5985 // average the vertex normals, find the surface bounds (after deformvertexes)
5986 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5987 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5988 VectorCopy(n, normal);
5989 VectorCopy(v, mins);
5990 VectorCopy(v, maxs);
5991 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5993 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5994 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5995 VectorAdd(normal, n, normal);
5996 mins[0] = min(mins[0], v[0]);
5997 mins[1] = min(mins[1], v[1]);
5998 mins[2] = min(mins[2], v[2]);
5999 maxs[0] = max(maxs[0], v[0]);
6000 maxs[1] = max(maxs[1], v[1]);
6001 maxs[2] = max(maxs[2], v[2]);
6003 VectorNormalize(normal);
6004 VectorMAM(0.5f, mins, 0.5f, maxs, center);
6006 VectorCopy(normal, plane.normal);
6007 VectorNormalize(plane.normal);
6008 plane.dist = DotProduct(center, plane.normal);
6009 PlaneClassify(&plane);
6010 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6012 // skip backfaces (except if nocullface is set)
6013 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6015 VectorNegate(plane.normal, plane.normal);
6017 PlaneClassify(&plane);
6021 // find a matching plane if there is one
6022 bestplaneindex = -1;
6023 bestplanescore = 1048576.0f;
6024 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6026 if(p->camera_entity == t->camera_entity)
6028 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6029 if (bestplaneindex < 0 || bestplanescore > planescore)
6031 bestplaneindex = planeindex;
6032 bestplanescore = planescore;
6036 planeindex = bestplaneindex;
6038 // if this surface does not fit any known plane rendered this frame, add one
6039 if (planeindex < 0 || bestplanescore > 0.001f)
6041 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6043 // store the new plane
6044 planeindex = r_fb.water.numwaterplanes++;
6045 p = r_fb.water.waterplanes + planeindex;
6047 // clear materialflags and pvs
6048 p->materialflags = 0;
6049 p->pvsvalid = false;
6050 p->camera_entity = t->camera_entity;
6051 VectorCopy(mins, p->mins);
6052 VectorCopy(maxs, p->maxs);
6056 // We're totally screwed.
6062 // merge mins/maxs when we're adding this surface to the plane
6063 p = r_fb.water.waterplanes + planeindex;
6064 p->mins[0] = min(p->mins[0], mins[0]);
6065 p->mins[1] = min(p->mins[1], mins[1]);
6066 p->mins[2] = min(p->mins[2], mins[2]);
6067 p->maxs[0] = max(p->maxs[0], maxs[0]);
6068 p->maxs[1] = max(p->maxs[1], maxs[1]);
6069 p->maxs[2] = max(p->maxs[2], maxs[2]);
6071 // merge this surface's materialflags into the waterplane
6072 p->materialflags |= t->currentmaterialflags;
6073 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6075 // merge this surface's PVS into the waterplane
6076 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6077 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6079 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6085 extern cvar_t r_drawparticles;
6086 extern cvar_t r_drawdecals;
6088 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6091 r_refdef_view_t originalview;
6092 r_refdef_view_t myview;
6093 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;
6094 r_waterstate_waterplane_t *p;
6096 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6099 originalview = r_refdef.view;
6101 // lowquality hack, temporarily shut down some cvars and restore afterwards
6102 qualityreduction = r_water_lowquality.integer;
6103 if (qualityreduction > 0)
6105 if (qualityreduction >= 1)
6107 old_r_shadows = r_shadows.integer;
6108 old_r_worldrtlight = r_shadow_realtime_world.integer;
6109 old_r_dlight = r_shadow_realtime_dlight.integer;
6110 Cvar_SetValueQuick(&r_shadows, 0);
6111 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6112 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6114 if (qualityreduction >= 2)
6116 old_r_dynamic = r_dynamic.integer;
6117 old_r_particles = r_drawparticles.integer;
6118 old_r_decals = r_drawdecals.integer;
6119 Cvar_SetValueQuick(&r_dynamic, 0);
6120 Cvar_SetValueQuick(&r_drawparticles, 0);
6121 Cvar_SetValueQuick(&r_drawdecals, 0);
6125 // make sure enough textures are allocated
6126 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6128 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6130 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6132 if (!p->texture_refraction)
6133 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6134 if (!p->texture_refraction)
6138 if (r_fb.water.depthtexture == NULL)
6139 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6140 if (p->fbo_refraction == 0)
6141 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6144 else if (p->materialflags & MATERIALFLAG_CAMERA)
6146 if (!p->texture_camera)
6147 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
6148 if (!p->texture_camera)
6152 if (r_fb.water.depthtexture == NULL)
6153 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6154 if (p->fbo_camera == 0)
6155 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6159 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6161 if (!p->texture_reflection)
6162 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6163 if (!p->texture_reflection)
6167 if (r_fb.water.depthtexture == NULL)
6168 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6169 if (p->fbo_reflection == 0)
6170 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6176 r_refdef.view = originalview;
6177 r_refdef.view.showdebug = false;
6178 r_refdef.view.width = r_fb.water.waterwidth;
6179 r_refdef.view.height = r_fb.water.waterheight;
6180 r_refdef.view.useclipplane = true;
6181 myview = r_refdef.view;
6182 r_fb.water.renderingscene = true;
6183 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6185 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6187 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6189 r_refdef.view = myview;
6190 if(r_water_scissormode.integer)
6192 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6193 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6194 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6197 // render reflected scene and copy into texture
6198 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6199 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6200 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6201 r_refdef.view.clipplane = p->plane;
6202 // reverse the cullface settings for this render
6203 r_refdef.view.cullface_front = GL_FRONT;
6204 r_refdef.view.cullface_back = GL_BACK;
6205 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6207 r_refdef.view.usecustompvs = true;
6209 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6211 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6214 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6215 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6216 R_ClearScreen(r_refdef.fogenabled);
6217 if(r_water_scissormode.integer & 2)
6218 R_View_UpdateWithScissor(myscissor);
6221 R_AnimCache_CacheVisibleEntities();
6222 if(r_water_scissormode.integer & 1)
6223 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6224 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6226 if (!p->fbo_reflection)
6227 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6228 r_fb.water.hideplayer = false;
6231 // render the normal view scene and copy into texture
6232 // (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)
6233 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6235 r_refdef.view = myview;
6236 if(r_water_scissormode.integer)
6238 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6239 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6240 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6243 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6245 r_refdef.view.clipplane = p->plane;
6246 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6247 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6249 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6251 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6252 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6253 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6254 R_RenderView_UpdateViewVectors();
6255 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6257 r_refdef.view.usecustompvs = true;
6258 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);
6262 PlaneClassify(&r_refdef.view.clipplane);
6264 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6265 R_ClearScreen(r_refdef.fogenabled);
6266 if(r_water_scissormode.integer & 2)
6267 R_View_UpdateWithScissor(myscissor);
6270 R_AnimCache_CacheVisibleEntities();
6271 if(r_water_scissormode.integer & 1)
6272 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6273 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6275 if (!p->fbo_refraction)
6276 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6277 r_fb.water.hideplayer = false;
6279 else if (p->materialflags & MATERIALFLAG_CAMERA)
6281 r_refdef.view = myview;
6283 r_refdef.view.clipplane = p->plane;
6284 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6285 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6287 r_refdef.view.width = r_fb.water.camerawidth;
6288 r_refdef.view.height = r_fb.water.cameraheight;
6289 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6290 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6291 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6292 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6294 if(p->camera_entity)
6296 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6297 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6300 // note: all of the view is used for displaying... so
6301 // there is no use in scissoring
6303 // reverse the cullface settings for this render
6304 r_refdef.view.cullface_front = GL_FRONT;
6305 r_refdef.view.cullface_back = GL_BACK;
6306 // also reverse the view matrix
6307 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
6308 R_RenderView_UpdateViewVectors();
6309 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6311 r_refdef.view.usecustompvs = true;
6312 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);
6315 // camera needs no clipplane
6316 r_refdef.view.useclipplane = false;
6318 PlaneClassify(&r_refdef.view.clipplane);
6320 r_fb.water.hideplayer = false;
6322 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6323 R_ClearScreen(r_refdef.fogenabled);
6325 R_AnimCache_CacheVisibleEntities();
6326 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6329 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6330 r_fb.water.hideplayer = false;
6334 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6335 r_fb.water.renderingscene = false;
6336 r_refdef.view = originalview;
6337 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6338 if (!r_fb.water.depthtexture)
6339 R_ClearScreen(r_refdef.fogenabled);
6341 R_AnimCache_CacheVisibleEntities();
6344 r_refdef.view = originalview;
6345 r_fb.water.renderingscene = false;
6346 Cvar_SetValueQuick(&r_water, 0);
6347 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6349 // lowquality hack, restore cvars
6350 if (qualityreduction > 0)
6352 if (qualityreduction >= 1)
6354 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6355 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6356 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6358 if (qualityreduction >= 2)
6360 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6361 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6362 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6367 static void R_Bloom_StartFrame(void)
6370 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6371 int viewwidth, viewheight;
6372 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6373 textype_t textype = TEXTYPE_COLORBUFFER;
6375 switch (vid.renderpath)
6377 case RENDERPATH_GL20:
6378 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6379 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6381 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6382 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6385 case RENDERPATH_GL11:
6386 case RENDERPATH_GL13:
6387 case RENDERPATH_GLES1:
6388 case RENDERPATH_GLES2:
6389 case RENDERPATH_D3D9:
6390 case RENDERPATH_D3D10:
6391 case RENDERPATH_D3D11:
6392 r_fb.usedepthtextures = false;
6394 case RENDERPATH_SOFT:
6395 r_fb.usedepthtextures = true;
6399 if (r_viewscale_fpsscaling.integer)
6401 double actualframetime;
6402 double targetframetime;
6404 actualframetime = r_refdef.lastdrawscreentime;
6405 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6406 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6407 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6408 if (r_viewscale_fpsscaling_stepsize.value > 0)
6409 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6410 viewscalefpsadjusted += adjust;
6411 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6414 viewscalefpsadjusted = 1.0f;
6416 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6418 switch(vid.renderpath)
6420 case RENDERPATH_GL20:
6421 case RENDERPATH_D3D9:
6422 case RENDERPATH_D3D10:
6423 case RENDERPATH_D3D11:
6424 case RENDERPATH_SOFT:
6425 case RENDERPATH_GLES2:
6427 case RENDERPATH_GL11:
6428 case RENDERPATH_GL13:
6429 case RENDERPATH_GLES1:
6433 // set bloomwidth and bloomheight to the bloom resolution that will be
6434 // used (often less than the screen resolution for faster rendering)
6435 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6436 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6437 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6438 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6439 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6441 // calculate desired texture sizes
6442 if (vid.support.arb_texture_non_power_of_two)
6444 screentexturewidth = vid.width;
6445 screentextureheight = vid.height;
6446 bloomtexturewidth = r_fb.bloomwidth;
6447 bloomtextureheight = r_fb.bloomheight;
6451 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6452 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6453 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6454 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6457 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))
6459 Cvar_SetValueQuick(&r_bloom, 0);
6460 Cvar_SetValueQuick(&r_motionblur, 0);
6461 Cvar_SetValueQuick(&r_damageblur, 0);
6464 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6466 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6468 && r_viewscale.value == 1.0f
6469 && !r_viewscale_fpsscaling.integer)
6470 screentexturewidth = screentextureheight = 0;
6471 if (!r_bloom.integer)
6472 bloomtexturewidth = bloomtextureheight = 0;
6474 // allocate textures as needed
6475 if (r_fb.screentexturewidth != screentexturewidth
6476 || r_fb.screentextureheight != screentextureheight
6477 || r_fb.bloomtexturewidth != bloomtexturewidth
6478 || r_fb.bloomtextureheight != bloomtextureheight
6479 || r_fb.textype != textype
6480 || useviewfbo != (r_fb.fbo != 0))
6482 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6484 if (r_fb.bloomtexture[i])
6485 R_FreeTexture(r_fb.bloomtexture[i]);
6486 r_fb.bloomtexture[i] = NULL;
6488 if (r_fb.bloomfbo[i])
6489 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6490 r_fb.bloomfbo[i] = 0;
6494 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6497 if (r_fb.colortexture)
6498 R_FreeTexture(r_fb.colortexture);
6499 r_fb.colortexture = NULL;
6501 if (r_fb.depthtexture)
6502 R_FreeTexture(r_fb.depthtexture);
6503 r_fb.depthtexture = NULL;
6505 if (r_fb.ghosttexture)
6506 R_FreeTexture(r_fb.ghosttexture);
6507 r_fb.ghosttexture = NULL;
6509 r_fb.screentexturewidth = screentexturewidth;
6510 r_fb.screentextureheight = screentextureheight;
6511 r_fb.bloomtexturewidth = bloomtexturewidth;
6512 r_fb.bloomtextureheight = bloomtextureheight;
6513 r_fb.textype = textype;
6515 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6517 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6518 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);
6519 r_fb.ghosttexture_valid = false;
6520 r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6523 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6524 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6525 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6529 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6531 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6533 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6535 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6540 // bloom texture is a different resolution
6541 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6542 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6543 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6544 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6545 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6547 // set up a texcoord array for the full resolution screen image
6548 // (we have to keep this around to copy back during final render)
6549 r_fb.screentexcoord2f[0] = 0;
6550 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6551 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6552 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6553 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6554 r_fb.screentexcoord2f[5] = 0;
6555 r_fb.screentexcoord2f[6] = 0;
6556 r_fb.screentexcoord2f[7] = 0;
6560 for (i = 1;i < 8;i += 2)
6562 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6566 // set up a texcoord array for the reduced resolution bloom image
6567 // (which will be additive blended over the screen image)
6568 r_fb.bloomtexcoord2f[0] = 0;
6569 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6570 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6571 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6572 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6573 r_fb.bloomtexcoord2f[5] = 0;
6574 r_fb.bloomtexcoord2f[6] = 0;
6575 r_fb.bloomtexcoord2f[7] = 0;
6577 switch(vid.renderpath)
6579 case RENDERPATH_GL11:
6580 case RENDERPATH_GL13:
6581 case RENDERPATH_GL20:
6582 case RENDERPATH_SOFT:
6583 case RENDERPATH_GLES1:
6584 case RENDERPATH_GLES2:
6586 case RENDERPATH_D3D9:
6587 case RENDERPATH_D3D10:
6588 case RENDERPATH_D3D11:
6589 for (i = 0;i < 4;i++)
6591 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6592 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6593 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6594 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6599 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6602 r_refdef.view.clear = true;
6605 static void R_Bloom_MakeTexture(void)
6608 float xoffset, yoffset, r, brighten;
6610 float colorscale = r_bloom_colorscale.value;
6612 r_refdef.stats[r_stat_bloom]++;
6615 // this copy is unnecessary since it happens in R_BlendView already
6618 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6619 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6623 // scale down screen texture to the bloom texture size
6625 r_fb.bloomindex = 0;
6626 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6627 R_SetViewport(&r_fb.bloomviewport);
6628 GL_CullFace(GL_NONE);
6629 GL_DepthTest(false);
6630 GL_BlendFunc(GL_ONE, GL_ZERO);
6631 GL_Color(colorscale, colorscale, colorscale, 1);
6632 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6633 switch(vid.renderpath)
6635 case RENDERPATH_GL11:
6636 case RENDERPATH_GL13:
6637 case RENDERPATH_GL20:
6638 case RENDERPATH_GLES1:
6639 case RENDERPATH_GLES2:
6640 case RENDERPATH_SOFT:
6641 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6643 case RENDERPATH_D3D9:
6644 case RENDERPATH_D3D10:
6645 case RENDERPATH_D3D11:
6646 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6649 // TODO: do boxfilter scale-down in shader?
6650 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6651 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6652 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6654 // we now have a properly scaled bloom image
6655 if (!r_fb.bloomfbo[r_fb.bloomindex])
6657 // copy it into the bloom texture
6658 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6659 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6662 // multiply bloom image by itself as many times as desired
6663 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6665 intex = r_fb.bloomtexture[r_fb.bloomindex];
6666 r_fb.bloomindex ^= 1;
6667 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6669 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6670 if (!r_fb.bloomfbo[r_fb.bloomindex])
6672 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6673 GL_Color(r,r,r,1); // apply fix factor
6678 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6679 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6680 GL_Color(1,1,1,1); // no fix factor supported here
6682 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6683 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6684 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6685 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6687 if (!r_fb.bloomfbo[r_fb.bloomindex])
6689 // copy the darkened image to a texture
6690 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6691 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6695 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6696 brighten = r_bloom_brighten.value;
6697 brighten = sqrt(brighten);
6699 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6701 for (dir = 0;dir < 2;dir++)
6703 intex = r_fb.bloomtexture[r_fb.bloomindex];
6704 r_fb.bloomindex ^= 1;
6705 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6706 // blend on at multiple vertical offsets to achieve a vertical blur
6707 // TODO: do offset blends using GLSL
6708 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6709 GL_BlendFunc(GL_ONE, GL_ZERO);
6710 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6711 for (x = -range;x <= range;x++)
6713 if (!dir){xoffset = 0;yoffset = x;}
6714 else {xoffset = x;yoffset = 0;}
6715 xoffset /= (float)r_fb.bloomtexturewidth;
6716 yoffset /= (float)r_fb.bloomtextureheight;
6717 // compute a texcoord array with the specified x and y offset
6718 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6719 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6720 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6721 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6722 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6723 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6724 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6725 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6726 // this r value looks like a 'dot' particle, fading sharply to
6727 // black at the edges
6728 // (probably not realistic but looks good enough)
6729 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6730 //r = brighten/(range*2+1);
6731 r = brighten / (range * 2 + 1);
6733 r *= (1 - x*x/(float)(range*range));
6734 GL_Color(r, r, r, 1);
6735 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6736 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6737 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6738 GL_BlendFunc(GL_ONE, GL_ONE);
6741 if (!r_fb.bloomfbo[r_fb.bloomindex])
6743 // copy the vertically or horizontally blurred bloom view to a texture
6744 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6745 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6750 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6752 unsigned int permutation;
6753 float uservecs[4][4];
6755 R_EntityMatrix(&identitymatrix);
6757 switch (vid.renderpath)
6759 case RENDERPATH_GL20:
6760 case RENDERPATH_D3D9:
6761 case RENDERPATH_D3D10:
6762 case RENDERPATH_D3D11:
6763 case RENDERPATH_SOFT:
6764 case RENDERPATH_GLES2:
6766 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6767 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6768 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6769 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6770 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6772 if (r_fb.colortexture)
6776 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6777 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6780 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6782 // declare variables
6783 float blur_factor, blur_mouseaccel, blur_velocity;
6784 static float blur_average;
6785 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6787 // set a goal for the factoring
6788 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6789 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6790 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6791 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6792 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6793 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6795 // from the goal, pick an averaged value between goal and last value
6796 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6797 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6799 // enforce minimum amount of blur
6800 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6802 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6804 // calculate values into a standard alpha
6805 cl.motionbluralpha = 1 - exp(-
6807 (r_motionblur.value * blur_factor / 80)
6809 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6812 max(0.0001, cl.time - cl.oldtime) // fps independent
6815 // randomization for the blur value to combat persistent ghosting
6816 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6817 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6820 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6821 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6823 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6824 GL_Color(1, 1, 1, cl.motionbluralpha);
6825 switch(vid.renderpath)
6827 case RENDERPATH_GL11:
6828 case RENDERPATH_GL13:
6829 case RENDERPATH_GL20:
6830 case RENDERPATH_GLES1:
6831 case RENDERPATH_GLES2:
6832 case RENDERPATH_SOFT:
6833 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6835 case RENDERPATH_D3D9:
6836 case RENDERPATH_D3D10:
6837 case RENDERPATH_D3D11:
6838 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6841 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6842 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6843 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6846 // updates old view angles for next pass
6847 VectorCopy(cl.viewangles, blur_oldangles);
6849 // copy view into the ghost texture
6850 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6851 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6852 r_fb.ghosttexture_valid = true;
6857 // no r_fb.colortexture means we're rendering to the real fb
6858 // we may still have to do view tint...
6859 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6861 // apply a color tint to the whole view
6862 R_ResetViewRendering2D(0, NULL, NULL);
6863 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6864 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6865 R_SetupShader_Generic_NoTexture(false, true);
6866 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6867 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6869 break; // no screen processing, no bloom, skip it
6872 if (r_fb.bloomtexture[0])
6874 // make the bloom texture
6875 R_Bloom_MakeTexture();
6878 #if _MSC_VER >= 1400
6879 #define sscanf sscanf_s
6881 memset(uservecs, 0, sizeof(uservecs));
6882 if (r_glsl_postprocess_uservec1_enable.integer)
6883 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6884 if (r_glsl_postprocess_uservec2_enable.integer)
6885 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6886 if (r_glsl_postprocess_uservec3_enable.integer)
6887 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6888 if (r_glsl_postprocess_uservec4_enable.integer)
6889 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6891 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6892 GL_Color(1, 1, 1, 1);
6893 GL_BlendFunc(GL_ONE, GL_ZERO);
6895 switch(vid.renderpath)
6897 case RENDERPATH_GL20:
6898 case RENDERPATH_GLES2:
6899 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6900 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6901 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6902 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6903 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6904 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]);
6905 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6906 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]);
6907 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]);
6908 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]);
6909 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]);
6910 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6911 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6912 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);
6914 case RENDERPATH_D3D9:
6916 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6917 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6918 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6919 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6920 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6921 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6922 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6923 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6924 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6925 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6926 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6927 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6928 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6929 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6930 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6933 case RENDERPATH_D3D10:
6934 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6936 case RENDERPATH_D3D11:
6937 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6939 case RENDERPATH_SOFT:
6940 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6941 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6942 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6943 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6944 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6945 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6946 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6947 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6948 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6949 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6950 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6951 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6952 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6953 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6958 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6959 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6961 case RENDERPATH_GL11:
6962 case RENDERPATH_GL13:
6963 case RENDERPATH_GLES1:
6964 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6966 // apply a color tint to the whole view
6967 R_ResetViewRendering2D(0, NULL, NULL);
6968 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6969 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6970 R_SetupShader_Generic_NoTexture(false, true);
6971 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6972 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6978 matrix4x4_t r_waterscrollmatrix;
6980 void R_UpdateFog(void)
6983 if (gamemode == GAME_NEHAHRA)
6985 if (gl_fogenable.integer)
6987 r_refdef.oldgl_fogenable = true;
6988 r_refdef.fog_density = gl_fogdensity.value;
6989 r_refdef.fog_red = gl_fogred.value;
6990 r_refdef.fog_green = gl_foggreen.value;
6991 r_refdef.fog_blue = gl_fogblue.value;
6992 r_refdef.fog_alpha = 1;
6993 r_refdef.fog_start = 0;
6994 r_refdef.fog_end = gl_skyclip.value;
6995 r_refdef.fog_height = 1<<30;
6996 r_refdef.fog_fadedepth = 128;
6998 else if (r_refdef.oldgl_fogenable)
7000 r_refdef.oldgl_fogenable = false;
7001 r_refdef.fog_density = 0;
7002 r_refdef.fog_red = 0;
7003 r_refdef.fog_green = 0;
7004 r_refdef.fog_blue = 0;
7005 r_refdef.fog_alpha = 0;
7006 r_refdef.fog_start = 0;
7007 r_refdef.fog_end = 0;
7008 r_refdef.fog_height = 1<<30;
7009 r_refdef.fog_fadedepth = 128;
7014 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7015 r_refdef.fog_start = max(0, r_refdef.fog_start);
7016 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7018 if (r_refdef.fog_density && r_drawfog.integer)
7020 r_refdef.fogenabled = true;
7021 // this is the point where the fog reaches 0.9986 alpha, which we
7022 // consider a good enough cutoff point for the texture
7023 // (0.9986 * 256 == 255.6)
7024 if (r_fog_exp2.integer)
7025 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7027 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7028 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7029 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7030 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7031 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7032 R_BuildFogHeightTexture();
7033 // fog color was already set
7034 // update the fog texture
7035 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)
7036 R_BuildFogTexture();
7037 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7038 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7041 r_refdef.fogenabled = false;
7044 if (r_refdef.fog_density)
7046 r_refdef.fogcolor[0] = r_refdef.fog_red;
7047 r_refdef.fogcolor[1] = r_refdef.fog_green;
7048 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7050 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7051 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7052 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7053 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7057 VectorCopy(r_refdef.fogcolor, fogvec);
7058 // color.rgb *= ContrastBoost * SceneBrightness;
7059 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7060 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7061 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7062 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7067 void R_UpdateVariables(void)
7071 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7073 r_refdef.farclip = r_farclip_base.value;
7074 if (r_refdef.scene.worldmodel)
7075 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7076 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7078 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7079 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7080 r_refdef.polygonfactor = 0;
7081 r_refdef.polygonoffset = 0;
7082 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7083 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7085 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7086 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7087 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7088 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7089 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7090 if (FAKELIGHT_ENABLED)
7092 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7094 else if (r_refdef.scene.worldmodel)
7096 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7098 if (r_showsurfaces.integer)
7100 r_refdef.scene.rtworld = false;
7101 r_refdef.scene.rtworldshadows = false;
7102 r_refdef.scene.rtdlight = false;
7103 r_refdef.scene.rtdlightshadows = false;
7104 r_refdef.lightmapintensity = 0;
7107 r_gpuskeletal = false;
7108 switch(vid.renderpath)
7110 case RENDERPATH_GL20:
7111 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7112 case RENDERPATH_D3D9:
7113 case RENDERPATH_D3D10:
7114 case RENDERPATH_D3D11:
7115 case RENDERPATH_SOFT:
7116 case RENDERPATH_GLES2:
7117 if(v_glslgamma.integer && !vid_gammatables_trivial)
7119 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7121 // build GLSL gamma texture
7122 #define RAMPWIDTH 256
7123 unsigned short ramp[RAMPWIDTH * 3];
7124 unsigned char rampbgr[RAMPWIDTH][4];
7127 r_texture_gammaramps_serial = vid_gammatables_serial;
7129 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7130 for(i = 0; i < RAMPWIDTH; ++i)
7132 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7133 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7134 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7137 if (r_texture_gammaramps)
7139 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7143 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7149 // remove GLSL gamma texture
7152 case RENDERPATH_GL11:
7153 case RENDERPATH_GL13:
7154 case RENDERPATH_GLES1:
7159 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7160 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7166 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7167 if( scenetype != r_currentscenetype ) {
7168 // store the old scenetype
7169 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7170 r_currentscenetype = scenetype;
7171 // move in the new scene
7172 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7181 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7183 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7184 if( scenetype == r_currentscenetype ) {
7185 return &r_refdef.scene;
7187 return &r_scenes_store[ scenetype ];
7191 static int R_SortEntities_Compare(const void *ap, const void *bp)
7193 const entity_render_t *a = *(const entity_render_t **)ap;
7194 const entity_render_t *b = *(const entity_render_t **)bp;
7197 if(a->model < b->model)
7199 if(a->model > b->model)
7203 // TODO possibly calculate the REAL skinnum here first using
7205 if(a->skinnum < b->skinnum)
7207 if(a->skinnum > b->skinnum)
7210 // everything we compared is equal
7213 static void R_SortEntities(void)
7215 // below or equal 2 ents, sorting never gains anything
7216 if(r_refdef.scene.numentities <= 2)
7219 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7227 int dpsoftrast_test;
7228 extern cvar_t r_shadow_bouncegrid;
7229 void R_RenderView(void)
7231 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7233 rtexture_t *depthtexture;
7234 rtexture_t *colortexture;
7236 dpsoftrast_test = r_test.integer;
7238 if (r_timereport_active)
7239 R_TimeReport("start");
7240 r_textureframe++; // used only by R_GetCurrentTexture
7241 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7243 if(R_CompileShader_CheckStaticParms())
7246 if (!r_drawentities.integer)
7247 r_refdef.scene.numentities = 0;
7248 else if (r_sortentities.integer)
7251 R_AnimCache_ClearCache();
7253 /* adjust for stereo display */
7254 if(R_Stereo_Active())
7256 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);
7257 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7260 if (r_refdef.view.isoverlay)
7262 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7263 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7264 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7265 R_TimeReport("depthclear");
7267 r_refdef.view.showdebug = false;
7269 r_fb.water.enabled = false;
7270 r_fb.water.numwaterplanes = 0;
7272 R_RenderScene(0, NULL, NULL);
7274 r_refdef.view.matrix = originalmatrix;
7280 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7282 r_refdef.view.matrix = originalmatrix;
7286 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7288 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7289 // in sRGB fallback, behave similar to true sRGB: convert this
7290 // value from linear to sRGB
7291 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7293 R_RenderView_UpdateViewVectors();
7295 R_Shadow_UpdateWorldLightSelection();
7297 R_Bloom_StartFrame();
7299 // apply bloom brightness offset
7300 if(r_fb.bloomtexture[0])
7301 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7303 R_Water_StartFrame();
7305 // now we probably have an fbo to render into
7307 depthtexture = r_fb.depthtexture;
7308 colortexture = r_fb.colortexture;
7311 if (r_timereport_active)
7312 R_TimeReport("viewsetup");
7314 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7316 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7318 R_ClearScreen(r_refdef.fogenabled);
7319 if (r_timereport_active)
7320 R_TimeReport("viewclear");
7322 r_refdef.view.clear = true;
7324 r_refdef.view.showdebug = true;
7327 if (r_timereport_active)
7328 R_TimeReport("visibility");
7330 R_AnimCache_CacheVisibleEntities();
7331 if (r_timereport_active)
7332 R_TimeReport("animcache");
7334 R_Shadow_UpdateBounceGridTexture();
7335 if (r_timereport_active && r_shadow_bouncegrid.integer)
7336 R_TimeReport("bouncegrid");
7338 r_fb.water.numwaterplanes = 0;
7339 if (r_fb.water.enabled)
7340 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7342 R_RenderScene(fbo, depthtexture, colortexture);
7343 r_fb.water.numwaterplanes = 0;
7345 R_BlendView(fbo, depthtexture, colortexture);
7346 if (r_timereport_active)
7347 R_TimeReport("blendview");
7349 GL_Scissor(0, 0, vid.width, vid.height);
7350 GL_ScissorTest(false);
7352 r_refdef.view.matrix = originalmatrix;
7357 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7359 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7361 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7362 if (r_timereport_active)
7363 R_TimeReport("waterworld");
7366 // don't let sound skip if going slow
7367 if (r_refdef.scene.extraupdate)
7370 R_DrawModelsAddWaterPlanes();
7371 if (r_timereport_active)
7372 R_TimeReport("watermodels");
7374 if (r_fb.water.numwaterplanes)
7376 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7377 if (r_timereport_active)
7378 R_TimeReport("waterscenes");
7382 extern cvar_t cl_locs_show;
7383 static void R_DrawLocs(void);
7384 static void R_DrawEntityBBoxes(void);
7385 static void R_DrawModelDecals(void);
7386 extern cvar_t cl_decals_newsystem;
7387 extern qboolean r_shadow_usingdeferredprepass;
7388 extern int r_shadow_shadowmapatlas_modelshadows_size;
7389 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7391 qboolean shadowmapping = false;
7393 if (r_timereport_active)
7394 R_TimeReport("beginscene");
7396 r_refdef.stats[r_stat_renders]++;
7400 // don't let sound skip if going slow
7401 if (r_refdef.scene.extraupdate)
7404 R_MeshQueue_BeginScene();
7408 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);
7410 if (r_timereport_active)
7411 R_TimeReport("skystartframe");
7413 if (cl.csqc_vidvars.drawworld)
7415 // don't let sound skip if going slow
7416 if (r_refdef.scene.extraupdate)
7419 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7421 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7422 if (r_timereport_active)
7423 R_TimeReport("worldsky");
7426 if (R_DrawBrushModelsSky() && r_timereport_active)
7427 R_TimeReport("bmodelsky");
7429 if (skyrendermasked && skyrenderlater)
7431 // we have to force off the water clipping plane while rendering sky
7432 R_SetupView(false, fbo, depthtexture, colortexture);
7434 R_SetupView(true, fbo, depthtexture, colortexture);
7435 if (r_timereport_active)
7436 R_TimeReport("sky");
7440 R_Shadow_PrepareModelShadows();
7441 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7442 if (r_timereport_active)
7443 R_TimeReport("preparelights");
7445 // render all the shadowmaps that will be used for this view
7446 shadowmapping = R_Shadow_ShadowMappingEnabled();
7447 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7449 R_Shadow_DrawShadowMaps();
7450 if (r_timereport_active)
7451 R_TimeReport("shadowmaps");
7454 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7455 if (r_shadow_usingdeferredprepass)
7456 R_Shadow_DrawPrepass();
7458 // now we begin the forward pass of the view render
7459 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7461 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7462 if (r_timereport_active)
7463 R_TimeReport("worlddepth");
7465 if (r_depthfirst.integer >= 2)
7467 R_DrawModelsDepth();
7468 if (r_timereport_active)
7469 R_TimeReport("modeldepth");
7472 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7474 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7475 if (r_timereport_active)
7476 R_TimeReport("world");
7479 // don't let sound skip if going slow
7480 if (r_refdef.scene.extraupdate)
7484 if (r_timereport_active)
7485 R_TimeReport("models");
7487 // don't let sound skip if going slow
7488 if (r_refdef.scene.extraupdate)
7491 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7493 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7494 R_Shadow_DrawModelShadows();
7495 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7496 // don't let sound skip if going slow
7497 if (r_refdef.scene.extraupdate)
7501 if (!r_shadow_usingdeferredprepass)
7503 R_Shadow_DrawLights();
7504 if (r_timereport_active)
7505 R_TimeReport("rtlights");
7508 // don't let sound skip if going slow
7509 if (r_refdef.scene.extraupdate)
7512 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7514 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7515 R_Shadow_DrawModelShadows();
7516 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7517 // don't let sound skip if going slow
7518 if (r_refdef.scene.extraupdate)
7522 if (cl.csqc_vidvars.drawworld)
7524 if (cl_decals_newsystem.integer)
7526 R_DrawModelDecals();
7527 if (r_timereport_active)
7528 R_TimeReport("modeldecals");
7533 if (r_timereport_active)
7534 R_TimeReport("decals");
7538 if (r_timereport_active)
7539 R_TimeReport("particles");
7542 if (r_timereport_active)
7543 R_TimeReport("explosions");
7545 R_DrawLightningBeams();
7546 if (r_timereport_active)
7547 R_TimeReport("lightning");
7551 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7553 if (r_refdef.view.showdebug)
7555 if (cl_locs_show.integer)
7558 if (r_timereport_active)
7559 R_TimeReport("showlocs");
7562 if (r_drawportals.integer)
7565 if (r_timereport_active)
7566 R_TimeReport("portals");
7569 if (r_showbboxes.value > 0)
7571 R_DrawEntityBBoxes();
7572 if (r_timereport_active)
7573 R_TimeReport("bboxes");
7577 if (r_transparent.integer)
7579 R_MeshQueue_RenderTransparent();
7580 if (r_timereport_active)
7581 R_TimeReport("drawtrans");
7584 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))
7586 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7587 if (r_timereport_active)
7588 R_TimeReport("worlddebug");
7589 R_DrawModelsDebug();
7590 if (r_timereport_active)
7591 R_TimeReport("modeldebug");
7594 if (cl.csqc_vidvars.drawworld)
7596 R_Shadow_DrawCoronas();
7597 if (r_timereport_active)
7598 R_TimeReport("coronas");
7603 GL_DepthTest(false);
7604 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7605 GL_Color(1, 1, 1, 1);
7606 qglBegin(GL_POLYGON);
7607 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7608 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7609 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7610 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7612 qglBegin(GL_POLYGON);
7613 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]);
7614 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]);
7615 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]);
7616 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]);
7618 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7622 // don't let sound skip if going slow
7623 if (r_refdef.scene.extraupdate)
7627 static const unsigned short bboxelements[36] =
7637 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7640 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7642 RSurf_ActiveWorldEntity();
7644 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7645 GL_DepthMask(false);
7646 GL_DepthRange(0, 1);
7647 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7648 // R_Mesh_ResetTextureState();
7650 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7651 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7652 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7653 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7654 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7655 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7656 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7657 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7658 R_FillColors(color4f, 8, cr, cg, cb, ca);
7659 if (r_refdef.fogenabled)
7661 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7663 f1 = RSurf_FogVertex(v);
7665 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7666 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7667 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7670 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7671 R_Mesh_ResetTextureState();
7672 R_SetupShader_Generic_NoTexture(false, false);
7673 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7676 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7678 prvm_prog_t *prog = SVVM_prog;
7681 prvm_edict_t *edict;
7683 // this function draws bounding boxes of server entities
7687 GL_CullFace(GL_NONE);
7688 R_SetupShader_Generic_NoTexture(false, false);
7690 for (i = 0;i < numsurfaces;i++)
7692 edict = PRVM_EDICT_NUM(surfacelist[i]);
7693 switch ((int)PRVM_serveredictfloat(edict, solid))
7695 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7696 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7697 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7698 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7699 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7700 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7701 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7703 color[3] *= r_showbboxes.value;
7704 color[3] = bound(0, color[3], 1);
7705 GL_DepthTest(!r_showdisabledepthtest.integer);
7706 GL_CullFace(r_refdef.view.cullface_front);
7707 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7711 static void R_DrawEntityBBoxes(void)
7714 prvm_edict_t *edict;
7716 prvm_prog_t *prog = SVVM_prog;
7718 // this function draws bounding boxes of server entities
7722 for (i = 0;i < prog->num_edicts;i++)
7724 edict = PRVM_EDICT_NUM(i);
7725 if (edict->priv.server->free)
7727 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7728 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7730 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7732 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7733 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7737 static const int nomodelelement3i[24] =
7749 static const unsigned short nomodelelement3s[24] =
7761 static const float nomodelvertex3f[6*3] =
7771 static const float nomodelcolor4f[6*4] =
7773 0.0f, 0.0f, 0.5f, 1.0f,
7774 0.0f, 0.0f, 0.5f, 1.0f,
7775 0.0f, 0.5f, 0.0f, 1.0f,
7776 0.0f, 0.5f, 0.0f, 1.0f,
7777 0.5f, 0.0f, 0.0f, 1.0f,
7778 0.5f, 0.0f, 0.0f, 1.0f
7781 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7787 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);
7789 // this is only called once per entity so numsurfaces is always 1, and
7790 // surfacelist is always {0}, so this code does not handle batches
7792 if (rsurface.ent_flags & RENDER_ADDITIVE)
7794 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7795 GL_DepthMask(false);
7797 else if (rsurface.colormod[3] < 1)
7799 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7800 GL_DepthMask(false);
7804 GL_BlendFunc(GL_ONE, GL_ZERO);
7807 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7808 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7809 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7810 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7811 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7812 for (i = 0, c = color4f;i < 6;i++, c += 4)
7814 c[0] *= rsurface.colormod[0];
7815 c[1] *= rsurface.colormod[1];
7816 c[2] *= rsurface.colormod[2];
7817 c[3] *= rsurface.colormod[3];
7819 if (r_refdef.fogenabled)
7821 for (i = 0, c = color4f;i < 6;i++, c += 4)
7823 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7825 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7826 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7827 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7830 // R_Mesh_ResetTextureState();
7831 R_SetupShader_Generic_NoTexture(false, false);
7832 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7833 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7836 void R_DrawNoModel(entity_render_t *ent)
7839 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7840 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7841 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7843 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7846 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7848 vec3_t right1, right2, diff, normal;
7850 VectorSubtract (org2, org1, normal);
7852 // calculate 'right' vector for start
7853 VectorSubtract (r_refdef.view.origin, org1, diff);
7854 CrossProduct (normal, diff, right1);
7855 VectorNormalize (right1);
7857 // calculate 'right' vector for end
7858 VectorSubtract (r_refdef.view.origin, org2, diff);
7859 CrossProduct (normal, diff, right2);
7860 VectorNormalize (right2);
7862 vert[ 0] = org1[0] + width * right1[0];
7863 vert[ 1] = org1[1] + width * right1[1];
7864 vert[ 2] = org1[2] + width * right1[2];
7865 vert[ 3] = org1[0] - width * right1[0];
7866 vert[ 4] = org1[1] - width * right1[1];
7867 vert[ 5] = org1[2] - width * right1[2];
7868 vert[ 6] = org2[0] - width * right2[0];
7869 vert[ 7] = org2[1] - width * right2[1];
7870 vert[ 8] = org2[2] - width * right2[2];
7871 vert[ 9] = org2[0] + width * right2[0];
7872 vert[10] = org2[1] + width * right2[1];
7873 vert[11] = org2[2] + width * right2[2];
7876 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)
7878 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7879 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7880 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7881 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7882 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7883 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7884 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7885 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7886 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7887 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7888 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7889 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7892 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7897 VectorSet(v, x, y, z);
7898 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7899 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7901 if (i == mesh->numvertices)
7903 if (mesh->numvertices < mesh->maxvertices)
7905 VectorCopy(v, vertex3f);
7906 mesh->numvertices++;
7908 return mesh->numvertices;
7914 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7918 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7919 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7920 e = mesh->element3i + mesh->numtriangles * 3;
7921 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7923 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7924 if (mesh->numtriangles < mesh->maxtriangles)
7929 mesh->numtriangles++;
7931 element[1] = element[2];
7935 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7939 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7940 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7941 e = mesh->element3i + mesh->numtriangles * 3;
7942 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7944 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7945 if (mesh->numtriangles < mesh->maxtriangles)
7950 mesh->numtriangles++;
7952 element[1] = element[2];
7956 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7957 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7959 int planenum, planenum2;
7962 mplane_t *plane, *plane2;
7964 double temppoints[2][256*3];
7965 // figure out how large a bounding box we need to properly compute this brush
7967 for (w = 0;w < numplanes;w++)
7968 maxdist = max(maxdist, fabs(planes[w].dist));
7969 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7970 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7971 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7975 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7976 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7978 if (planenum2 == planenum)
7980 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);
7983 if (tempnumpoints < 3)
7985 // generate elements forming a triangle fan for this polygon
7986 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7990 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)
7992 texturelayer_t *layer;
7993 layer = t->currentlayers + t->currentnumlayers++;
7995 layer->depthmask = depthmask;
7996 layer->blendfunc1 = blendfunc1;
7997 layer->blendfunc2 = blendfunc2;
7998 layer->texture = texture;
7999 layer->texmatrix = *matrix;
8000 layer->color[0] = r;
8001 layer->color[1] = g;
8002 layer->color[2] = b;
8003 layer->color[3] = a;
8006 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8008 if(parms[0] == 0 && parms[1] == 0)
8010 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8011 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8016 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8019 index = parms[2] + rsurface.shadertime * parms[3];
8020 index -= floor(index);
8021 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8024 case Q3WAVEFUNC_NONE:
8025 case Q3WAVEFUNC_NOISE:
8026 case Q3WAVEFUNC_COUNT:
8029 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8030 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8031 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8032 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8033 case Q3WAVEFUNC_TRIANGLE:
8035 f = index - floor(index);
8048 f = parms[0] + parms[1] * f;
8049 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8050 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8054 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8061 matrix4x4_t matrix, temp;
8062 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8063 // it's better to have one huge fixup every 9 hours than gradual
8064 // degradation over time which looks consistently bad after many hours.
8066 // tcmod scroll in particular suffers from this degradation which can't be
8067 // effectively worked around even with floor() tricks because we don't
8068 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8069 // a workaround involving floor() would be incorrect anyway...
8070 shadertime = rsurface.shadertime;
8071 if (shadertime >= 32768.0f)
8072 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8073 switch(tcmod->tcmod)
8077 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8078 matrix = r_waterscrollmatrix;
8080 matrix = identitymatrix;
8082 case Q3TCMOD_ENTITYTRANSLATE:
8083 // this is used in Q3 to allow the gamecode to control texcoord
8084 // scrolling on the entity, which is not supported in darkplaces yet.
8085 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8087 case Q3TCMOD_ROTATE:
8088 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8089 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8090 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8093 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8095 case Q3TCMOD_SCROLL:
8096 // this particular tcmod is a "bug for bug" compatible one with regards to
8097 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8098 // specifically did the wrapping and so we must mimic that...
8099 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8100 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8101 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8103 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8104 w = (int) tcmod->parms[0];
8105 h = (int) tcmod->parms[1];
8106 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8108 idx = (int) floor(f * w * h);
8109 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8111 case Q3TCMOD_STRETCH:
8112 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8113 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8115 case Q3TCMOD_TRANSFORM:
8116 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8117 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8118 VectorSet(tcmat + 6, 0 , 0 , 1);
8119 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8120 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8122 case Q3TCMOD_TURBULENT:
8123 // this is handled in the RSurf_PrepareVertices function
8124 matrix = identitymatrix;
8128 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8131 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8133 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8134 char name[MAX_QPATH];
8135 skinframe_t *skinframe;
8136 unsigned char pixels[296*194];
8137 strlcpy(cache->name, skinname, sizeof(cache->name));
8138 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8139 if (developer_loading.integer)
8140 Con_Printf("loading %s\n", name);
8141 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8142 if (!skinframe || !skinframe->base)
8145 fs_offset_t filesize;
8147 f = FS_LoadFile(name, tempmempool, true, &filesize);
8150 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8151 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8155 cache->skinframe = skinframe;
8158 texture_t *R_GetCurrentTexture(texture_t *t)
8161 const entity_render_t *ent = rsurface.entity;
8162 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8163 q3shaderinfo_layer_tcmod_t *tcmod;
8165 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8166 return t->currentframe;
8167 t->update_lastrenderframe = r_textureframe;
8168 t->update_lastrenderentity = (void *)ent;
8170 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8171 t->camera_entity = ent->entitynumber;
8173 t->camera_entity = 0;
8175 // switch to an alternate material if this is a q1bsp animated material
8177 texture_t *texture = t;
8178 int s = rsurface.ent_skinnum;
8179 if ((unsigned int)s >= (unsigned int)model->numskins)
8181 if (model->skinscenes)
8183 if (model->skinscenes[s].framecount > 1)
8184 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8186 s = model->skinscenes[s].firstframe;
8189 t = t + s * model->num_surfaces;
8192 // use an alternate animation if the entity's frame is not 0,
8193 // and only if the texture has an alternate animation
8194 if (t->animated == 2) // q2bsp
8195 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8196 else if (rsurface.ent_alttextures && t->anim_total[1])
8197 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8199 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8201 texture->currentframe = t;
8204 // update currentskinframe to be a qw skin or animation frame
8205 if (rsurface.ent_qwskin >= 0)
8207 i = rsurface.ent_qwskin;
8208 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8210 r_qwskincache_size = cl.maxclients;
8212 Mem_Free(r_qwskincache);
8213 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8215 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8216 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8217 t->currentskinframe = r_qwskincache[i].skinframe;
8218 if (t->materialshaderpass && t->currentskinframe == NULL)
8219 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8221 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8222 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8223 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8224 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8226 t->currentmaterialflags = t->basematerialflags;
8227 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8228 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8229 t->currentalpha *= r_wateralpha.value;
8230 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8231 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8232 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8233 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8234 if (!(rsurface.ent_flags & RENDER_LIGHT))
8235 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8236 else if (FAKELIGHT_ENABLED)
8238 // no modellight if using fakelight for the map
8240 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8242 // pick a model lighting mode
8243 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8244 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8246 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8248 if (rsurface.ent_flags & RENDER_ADDITIVE)
8249 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8250 else if (t->currentalpha < 1)
8251 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8252 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8253 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8254 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8255 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8256 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8257 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8258 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8259 if (t->backgroundshaderpass)
8260 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8261 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8263 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8264 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8267 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8268 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8270 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8271 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8273 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8274 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8276 // there is no tcmod
8277 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8279 t->currenttexmatrix = r_waterscrollmatrix;
8280 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8282 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8284 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8285 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8288 if (t->materialshaderpass)
8289 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8290 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8292 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8293 if (t->currentskinframe->qpixels)
8294 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8295 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8296 if (!t->basetexture)
8297 t->basetexture = r_texture_notexture;
8298 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8299 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8300 t->nmaptexture = t->currentskinframe->nmap;
8301 if (!t->nmaptexture)
8302 t->nmaptexture = r_texture_blanknormalmap;
8303 t->glosstexture = r_texture_black;
8304 t->glowtexture = t->currentskinframe->glow;
8305 t->fogtexture = t->currentskinframe->fog;
8306 t->reflectmasktexture = t->currentskinframe->reflect;
8307 if (t->backgroundshaderpass)
8309 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8310 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8311 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8312 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8313 t->backgroundglosstexture = r_texture_black;
8314 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8315 if (!t->backgroundnmaptexture)
8316 t->backgroundnmaptexture = r_texture_blanknormalmap;
8317 // make sure that if glow is going to be used, both textures are not NULL
8318 if (!t->backgroundglowtexture && t->glowtexture)
8319 t->backgroundglowtexture = r_texture_black;
8320 if (!t->glowtexture && t->backgroundglowtexture)
8321 t->glowtexture = r_texture_black;
8325 t->backgroundbasetexture = r_texture_white;
8326 t->backgroundnmaptexture = r_texture_blanknormalmap;
8327 t->backgroundglosstexture = r_texture_black;
8328 t->backgroundglowtexture = NULL;
8330 t->specularpower = r_shadow_glossexponent.value;
8331 // TODO: store reference values for these in the texture?
8332 t->specularscale = 0;
8333 if (r_shadow_gloss.integer > 0)
8335 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8337 if (r_shadow_glossintensity.value > 0)
8339 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8340 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8341 t->specularscale = r_shadow_glossintensity.value;
8344 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8346 t->glosstexture = r_texture_white;
8347 t->backgroundglosstexture = r_texture_white;
8348 t->specularscale = r_shadow_gloss2intensity.value;
8349 t->specularpower = r_shadow_gloss2exponent.value;
8352 t->specularscale *= t->specularscalemod;
8353 t->specularpower *= t->specularpowermod;
8354 t->rtlightambient = 0;
8356 // lightmaps mode looks bad with dlights using actual texturing, so turn
8357 // off the colormap and glossmap, but leave the normalmap on as it still
8358 // accurately represents the shading involved
8359 if (gl_lightmaps.integer)
8361 t->basetexture = r_texture_grey128;
8362 t->pantstexture = r_texture_black;
8363 t->shirttexture = r_texture_black;
8364 if (gl_lightmaps.integer < 2)
8365 t->nmaptexture = r_texture_blanknormalmap;
8366 t->glosstexture = r_texture_black;
8367 t->glowtexture = NULL;
8368 t->fogtexture = NULL;
8369 t->reflectmasktexture = NULL;
8370 t->backgroundbasetexture = NULL;
8371 if (gl_lightmaps.integer < 2)
8372 t->backgroundnmaptexture = r_texture_blanknormalmap;
8373 t->backgroundglosstexture = r_texture_black;
8374 t->backgroundglowtexture = NULL;
8375 t->specularscale = 0;
8376 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8379 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8380 VectorClear(t->dlightcolor);
8381 t->currentnumlayers = 0;
8382 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8384 int blendfunc1, blendfunc2;
8386 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8388 blendfunc1 = GL_SRC_ALPHA;
8389 blendfunc2 = GL_ONE;
8391 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8393 blendfunc1 = GL_SRC_ALPHA;
8394 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8396 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8398 blendfunc1 = t->customblendfunc[0];
8399 blendfunc2 = t->customblendfunc[1];
8403 blendfunc1 = GL_ONE;
8404 blendfunc2 = GL_ZERO;
8406 // don't colormod evilblend textures
8407 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8408 VectorSet(t->lightmapcolor, 1, 1, 1);
8409 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8410 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8412 // fullbright is not affected by r_refdef.lightmapintensity
8413 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8414 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8415 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8416 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8417 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8421 vec3_t ambientcolor;
8423 // set the color tint used for lights affecting this surface
8424 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8426 // q3bsp has no lightmap updates, so the lightstylevalue that
8427 // would normally be baked into the lightmap must be
8428 // applied to the color
8429 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8430 if (model->type == mod_brushq3)
8431 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8432 colorscale *= r_refdef.lightmapintensity;
8433 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8434 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8435 // basic lit geometry
8436 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8437 // add pants/shirt if needed
8438 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8439 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8440 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8441 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8442 // now add ambient passes if needed
8443 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8445 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
8446 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8447 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8448 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8449 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8452 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8453 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8454 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8456 // if this is opaque use alpha blend which will darken the earlier
8459 // if this is an alpha blended material, all the earlier passes
8460 // were darkened by fog already, so we only need to add the fog
8461 // color ontop through the fog mask texture
8463 // if this is an additive blended material, all the earlier passes
8464 // were darkened by fog already, and we should not add fog color
8465 // (because the background was not darkened, there is no fog color
8466 // that was lost behind it).
8467 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->lightmapcolor[3]);
8474 rsurfacestate_t rsurface;
8476 void RSurf_ActiveWorldEntity(void)
8478 dp_model_t *model = r_refdef.scene.worldmodel;
8479 //if (rsurface.entity == r_refdef.scene.worldentity)
8481 rsurface.entity = r_refdef.scene.worldentity;
8482 rsurface.skeleton = NULL;
8483 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8484 rsurface.ent_skinnum = 0;
8485 rsurface.ent_qwskin = -1;
8486 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8487 rsurface.shadertime = r_refdef.scene.time;
8488 rsurface.matrix = identitymatrix;
8489 rsurface.inversematrix = identitymatrix;
8490 rsurface.matrixscale = 1;
8491 rsurface.inversematrixscale = 1;
8492 R_EntityMatrix(&identitymatrix);
8493 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8494 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8495 rsurface.fograngerecip = r_refdef.fograngerecip;
8496 rsurface.fogheightfade = r_refdef.fogheightfade;
8497 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8498 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8499 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8500 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8501 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8502 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8503 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8504 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8505 rsurface.colormod[3] = 1;
8506 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8507 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8508 rsurface.frameblend[0].lerp = 1;
8509 rsurface.ent_alttextures = false;
8510 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8511 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8512 rsurface.entityskeletaltransform3x4 = NULL;
8513 rsurface.entityskeletaltransform3x4buffer = NULL;
8514 rsurface.entityskeletaltransform3x4offset = 0;
8515 rsurface.entityskeletaltransform3x4size = 0;;
8516 rsurface.entityskeletalnumtransforms = 0;
8517 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8518 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8519 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8520 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8521 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8522 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8523 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8524 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8525 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8526 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8527 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8528 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8529 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8530 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8531 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8532 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8533 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8534 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8535 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8536 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8537 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8538 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8539 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8540 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8541 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8542 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8543 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8544 rsurface.modelelement3i = model->surfmesh.data_element3i;
8545 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8546 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8547 rsurface.modelelement3s = model->surfmesh.data_element3s;
8548 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8549 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8550 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8551 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8552 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8553 rsurface.modelsurfaces = model->data_surfaces;
8554 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8555 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8556 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8557 rsurface.modelgeneratedvertex = false;
8558 rsurface.batchgeneratedvertex = false;
8559 rsurface.batchfirstvertex = 0;
8560 rsurface.batchnumvertices = 0;
8561 rsurface.batchfirsttriangle = 0;
8562 rsurface.batchnumtriangles = 0;
8563 rsurface.batchvertex3f = NULL;
8564 rsurface.batchvertex3f_vertexbuffer = NULL;
8565 rsurface.batchvertex3f_bufferoffset = 0;
8566 rsurface.batchsvector3f = NULL;
8567 rsurface.batchsvector3f_vertexbuffer = NULL;
8568 rsurface.batchsvector3f_bufferoffset = 0;
8569 rsurface.batchtvector3f = NULL;
8570 rsurface.batchtvector3f_vertexbuffer = NULL;
8571 rsurface.batchtvector3f_bufferoffset = 0;
8572 rsurface.batchnormal3f = NULL;
8573 rsurface.batchnormal3f_vertexbuffer = NULL;
8574 rsurface.batchnormal3f_bufferoffset = 0;
8575 rsurface.batchlightmapcolor4f = NULL;
8576 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8577 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8578 rsurface.batchtexcoordtexture2f = NULL;
8579 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8580 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8581 rsurface.batchtexcoordlightmap2f = NULL;
8582 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8583 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8584 rsurface.batchskeletalindex4ub = NULL;
8585 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8586 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8587 rsurface.batchskeletalweight4ub = NULL;
8588 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8589 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8590 rsurface.batchvertexmesh = NULL;
8591 rsurface.batchvertexmesh_vertexbuffer = NULL;
8592 rsurface.batchvertexmesh_bufferoffset = 0;
8593 rsurface.batchelement3i = NULL;
8594 rsurface.batchelement3i_indexbuffer = NULL;
8595 rsurface.batchelement3i_bufferoffset = 0;
8596 rsurface.batchelement3s = NULL;
8597 rsurface.batchelement3s_indexbuffer = NULL;
8598 rsurface.batchelement3s_bufferoffset = 0;
8599 rsurface.passcolor4f = NULL;
8600 rsurface.passcolor4f_vertexbuffer = NULL;
8601 rsurface.passcolor4f_bufferoffset = 0;
8602 rsurface.forcecurrenttextureupdate = false;
8605 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8607 dp_model_t *model = ent->model;
8608 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8610 rsurface.entity = (entity_render_t *)ent;
8611 rsurface.skeleton = ent->skeleton;
8612 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8613 rsurface.ent_skinnum = ent->skinnum;
8614 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;
8615 rsurface.ent_flags = ent->flags;
8616 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8617 rsurface.matrix = ent->matrix;
8618 rsurface.inversematrix = ent->inversematrix;
8619 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8620 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8621 R_EntityMatrix(&rsurface.matrix);
8622 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8623 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8624 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8625 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8626 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8627 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8628 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8629 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8630 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8631 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8632 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8633 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8634 rsurface.colormod[3] = ent->alpha;
8635 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8636 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8637 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8638 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8639 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8640 if (ent->model->brush.submodel && !prepass)
8642 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8643 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8645 // if the animcache code decided it should use the shader path, skip the deform step
8646 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8647 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8648 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8649 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8650 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8651 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8653 if (ent->animcache_vertex3f)
8655 r_refdef.stats[r_stat_batch_entitycache_count]++;
8656 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8657 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8658 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8659 rsurface.modelvertex3f = ent->animcache_vertex3f;
8660 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8661 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8662 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8663 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8664 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8665 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8666 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8667 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8668 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8669 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8670 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8671 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8672 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8673 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8675 else if (wanttangents)
8677 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8678 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8679 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8680 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8681 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8682 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8683 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8684 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8685 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8686 rsurface.modelvertexmesh = NULL;
8687 rsurface.modelvertexmesh_vertexbuffer = NULL;
8688 rsurface.modelvertexmesh_bufferoffset = 0;
8689 rsurface.modelvertex3f_vertexbuffer = NULL;
8690 rsurface.modelvertex3f_bufferoffset = 0;
8691 rsurface.modelvertex3f_vertexbuffer = 0;
8692 rsurface.modelvertex3f_bufferoffset = 0;
8693 rsurface.modelsvector3f_vertexbuffer = 0;
8694 rsurface.modelsvector3f_bufferoffset = 0;
8695 rsurface.modeltvector3f_vertexbuffer = 0;
8696 rsurface.modeltvector3f_bufferoffset = 0;
8697 rsurface.modelnormal3f_vertexbuffer = 0;
8698 rsurface.modelnormal3f_bufferoffset = 0;
8700 else if (wantnormals)
8702 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8703 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8704 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8705 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8706 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8707 rsurface.modelsvector3f = NULL;
8708 rsurface.modeltvector3f = NULL;
8709 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8710 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8711 rsurface.modelvertexmesh = NULL;
8712 rsurface.modelvertexmesh_vertexbuffer = NULL;
8713 rsurface.modelvertexmesh_bufferoffset = 0;
8714 rsurface.modelvertex3f_vertexbuffer = NULL;
8715 rsurface.modelvertex3f_bufferoffset = 0;
8716 rsurface.modelvertex3f_vertexbuffer = 0;
8717 rsurface.modelvertex3f_bufferoffset = 0;
8718 rsurface.modelsvector3f_vertexbuffer = 0;
8719 rsurface.modelsvector3f_bufferoffset = 0;
8720 rsurface.modeltvector3f_vertexbuffer = 0;
8721 rsurface.modeltvector3f_bufferoffset = 0;
8722 rsurface.modelnormal3f_vertexbuffer = 0;
8723 rsurface.modelnormal3f_bufferoffset = 0;
8727 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8728 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8729 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8730 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8731 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8732 rsurface.modelsvector3f = NULL;
8733 rsurface.modeltvector3f = NULL;
8734 rsurface.modelnormal3f = NULL;
8735 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8736 rsurface.modelvertexmesh = NULL;
8737 rsurface.modelvertexmesh_vertexbuffer = NULL;
8738 rsurface.modelvertexmesh_bufferoffset = 0;
8739 rsurface.modelvertex3f_vertexbuffer = NULL;
8740 rsurface.modelvertex3f_bufferoffset = 0;
8741 rsurface.modelvertex3f_vertexbuffer = 0;
8742 rsurface.modelvertex3f_bufferoffset = 0;
8743 rsurface.modelsvector3f_vertexbuffer = 0;
8744 rsurface.modelsvector3f_bufferoffset = 0;
8745 rsurface.modeltvector3f_vertexbuffer = 0;
8746 rsurface.modeltvector3f_bufferoffset = 0;
8747 rsurface.modelnormal3f_vertexbuffer = 0;
8748 rsurface.modelnormal3f_bufferoffset = 0;
8750 rsurface.modelgeneratedvertex = true;
8754 if (rsurface.entityskeletaltransform3x4)
8756 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8757 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8758 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8759 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8763 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8764 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8765 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8766 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8768 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8769 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8770 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8771 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8772 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8773 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8774 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8775 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8776 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8777 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8778 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8779 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8780 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8781 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8782 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8783 rsurface.modelgeneratedvertex = false;
8785 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8786 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8787 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8788 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8789 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8790 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8791 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8792 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8793 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8794 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8795 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8796 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8797 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8798 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8799 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8800 rsurface.modelelement3i = model->surfmesh.data_element3i;
8801 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8802 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8803 rsurface.modelelement3s = model->surfmesh.data_element3s;
8804 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8805 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8806 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8807 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8808 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8809 rsurface.modelsurfaces = model->data_surfaces;
8810 rsurface.batchgeneratedvertex = false;
8811 rsurface.batchfirstvertex = 0;
8812 rsurface.batchnumvertices = 0;
8813 rsurface.batchfirsttriangle = 0;
8814 rsurface.batchnumtriangles = 0;
8815 rsurface.batchvertex3f = NULL;
8816 rsurface.batchvertex3f_vertexbuffer = NULL;
8817 rsurface.batchvertex3f_bufferoffset = 0;
8818 rsurface.batchsvector3f = NULL;
8819 rsurface.batchsvector3f_vertexbuffer = NULL;
8820 rsurface.batchsvector3f_bufferoffset = 0;
8821 rsurface.batchtvector3f = NULL;
8822 rsurface.batchtvector3f_vertexbuffer = NULL;
8823 rsurface.batchtvector3f_bufferoffset = 0;
8824 rsurface.batchnormal3f = NULL;
8825 rsurface.batchnormal3f_vertexbuffer = NULL;
8826 rsurface.batchnormal3f_bufferoffset = 0;
8827 rsurface.batchlightmapcolor4f = NULL;
8828 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8829 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8830 rsurface.batchtexcoordtexture2f = NULL;
8831 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8832 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8833 rsurface.batchtexcoordlightmap2f = NULL;
8834 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8835 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8836 rsurface.batchskeletalindex4ub = NULL;
8837 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8838 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8839 rsurface.batchskeletalweight4ub = NULL;
8840 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8841 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8842 rsurface.batchvertexmesh = NULL;
8843 rsurface.batchvertexmesh_vertexbuffer = NULL;
8844 rsurface.batchvertexmesh_bufferoffset = 0;
8845 rsurface.batchelement3i = NULL;
8846 rsurface.batchelement3i_indexbuffer = NULL;
8847 rsurface.batchelement3i_bufferoffset = 0;
8848 rsurface.batchelement3s = NULL;
8849 rsurface.batchelement3s_indexbuffer = NULL;
8850 rsurface.batchelement3s_bufferoffset = 0;
8851 rsurface.passcolor4f = NULL;
8852 rsurface.passcolor4f_vertexbuffer = NULL;
8853 rsurface.passcolor4f_bufferoffset = 0;
8854 rsurface.forcecurrenttextureupdate = false;
8857 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)
8859 rsurface.entity = r_refdef.scene.worldentity;
8860 rsurface.skeleton = NULL;
8861 rsurface.ent_skinnum = 0;
8862 rsurface.ent_qwskin = -1;
8863 rsurface.ent_flags = entflags;
8864 rsurface.shadertime = r_refdef.scene.time - shadertime;
8865 rsurface.modelnumvertices = numvertices;
8866 rsurface.modelnumtriangles = numtriangles;
8867 rsurface.matrix = *matrix;
8868 rsurface.inversematrix = *inversematrix;
8869 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8870 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8871 R_EntityMatrix(&rsurface.matrix);
8872 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8873 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8874 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8875 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8876 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8877 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8878 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8879 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8880 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8881 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8882 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8883 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8884 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8885 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8886 rsurface.frameblend[0].lerp = 1;
8887 rsurface.ent_alttextures = false;
8888 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8889 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8890 rsurface.entityskeletaltransform3x4 = NULL;
8891 rsurface.entityskeletaltransform3x4buffer = NULL;
8892 rsurface.entityskeletaltransform3x4offset = 0;
8893 rsurface.entityskeletaltransform3x4size = 0;
8894 rsurface.entityskeletalnumtransforms = 0;
8895 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8896 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8897 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8898 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8901 rsurface.modelvertex3f = (float *)vertex3f;
8902 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8903 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8904 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8906 else if (wantnormals)
8908 rsurface.modelvertex3f = (float *)vertex3f;
8909 rsurface.modelsvector3f = NULL;
8910 rsurface.modeltvector3f = NULL;
8911 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8915 rsurface.modelvertex3f = (float *)vertex3f;
8916 rsurface.modelsvector3f = NULL;
8917 rsurface.modeltvector3f = NULL;
8918 rsurface.modelnormal3f = NULL;
8920 rsurface.modelvertexmesh = NULL;
8921 rsurface.modelvertexmesh_vertexbuffer = NULL;
8922 rsurface.modelvertexmesh_bufferoffset = 0;
8923 rsurface.modelvertex3f_vertexbuffer = 0;
8924 rsurface.modelvertex3f_bufferoffset = 0;
8925 rsurface.modelsvector3f_vertexbuffer = 0;
8926 rsurface.modelsvector3f_bufferoffset = 0;
8927 rsurface.modeltvector3f_vertexbuffer = 0;
8928 rsurface.modeltvector3f_bufferoffset = 0;
8929 rsurface.modelnormal3f_vertexbuffer = 0;
8930 rsurface.modelnormal3f_bufferoffset = 0;
8931 rsurface.modelgeneratedvertex = true;
8932 rsurface.modellightmapcolor4f = (float *)color4f;
8933 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8934 rsurface.modellightmapcolor4f_bufferoffset = 0;
8935 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8936 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8937 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8938 rsurface.modeltexcoordlightmap2f = NULL;
8939 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8940 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8941 rsurface.modelskeletalindex4ub = NULL;
8942 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8943 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8944 rsurface.modelskeletalweight4ub = NULL;
8945 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8946 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8947 rsurface.modelelement3i = (int *)element3i;
8948 rsurface.modelelement3i_indexbuffer = NULL;
8949 rsurface.modelelement3i_bufferoffset = 0;
8950 rsurface.modelelement3s = (unsigned short *)element3s;
8951 rsurface.modelelement3s_indexbuffer = NULL;
8952 rsurface.modelelement3s_bufferoffset = 0;
8953 rsurface.modellightmapoffsets = NULL;
8954 rsurface.modelsurfaces = NULL;
8955 rsurface.batchgeneratedvertex = false;
8956 rsurface.batchfirstvertex = 0;
8957 rsurface.batchnumvertices = 0;
8958 rsurface.batchfirsttriangle = 0;
8959 rsurface.batchnumtriangles = 0;
8960 rsurface.batchvertex3f = NULL;
8961 rsurface.batchvertex3f_vertexbuffer = NULL;
8962 rsurface.batchvertex3f_bufferoffset = 0;
8963 rsurface.batchsvector3f = NULL;
8964 rsurface.batchsvector3f_vertexbuffer = NULL;
8965 rsurface.batchsvector3f_bufferoffset = 0;
8966 rsurface.batchtvector3f = NULL;
8967 rsurface.batchtvector3f_vertexbuffer = NULL;
8968 rsurface.batchtvector3f_bufferoffset = 0;
8969 rsurface.batchnormal3f = NULL;
8970 rsurface.batchnormal3f_vertexbuffer = NULL;
8971 rsurface.batchnormal3f_bufferoffset = 0;
8972 rsurface.batchlightmapcolor4f = NULL;
8973 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8974 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8975 rsurface.batchtexcoordtexture2f = NULL;
8976 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8977 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8978 rsurface.batchtexcoordlightmap2f = NULL;
8979 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8980 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8981 rsurface.batchskeletalindex4ub = NULL;
8982 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8983 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8984 rsurface.batchskeletalweight4ub = NULL;
8985 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8986 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8987 rsurface.batchvertexmesh = NULL;
8988 rsurface.batchvertexmesh_vertexbuffer = NULL;
8989 rsurface.batchvertexmesh_bufferoffset = 0;
8990 rsurface.batchelement3i = NULL;
8991 rsurface.batchelement3i_indexbuffer = NULL;
8992 rsurface.batchelement3i_bufferoffset = 0;
8993 rsurface.batchelement3s = NULL;
8994 rsurface.batchelement3s_indexbuffer = NULL;
8995 rsurface.batchelement3s_bufferoffset = 0;
8996 rsurface.passcolor4f = NULL;
8997 rsurface.passcolor4f_vertexbuffer = NULL;
8998 rsurface.passcolor4f_bufferoffset = 0;
8999 rsurface.forcecurrenttextureupdate = true;
9001 if (rsurface.modelnumvertices && rsurface.modelelement3i)
9003 if ((wantnormals || wanttangents) && !normal3f)
9005 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9006 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9008 if (wanttangents && !svector3f)
9010 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9011 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9012 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9017 float RSurf_FogPoint(const float *v)
9019 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9020 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9021 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9022 float FogHeightFade = r_refdef.fogheightfade;
9024 unsigned int fogmasktableindex;
9025 if (r_refdef.fogplaneviewabove)
9026 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9028 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9029 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9030 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9033 float RSurf_FogVertex(const float *v)
9035 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9036 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9037 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9038 float FogHeightFade = rsurface.fogheightfade;
9040 unsigned int fogmasktableindex;
9041 if (r_refdef.fogplaneviewabove)
9042 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9044 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9045 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9046 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9049 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9052 for (i = 0;i < numelements;i++)
9053 outelement3i[i] = inelement3i[i] + adjust;
9056 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9057 extern cvar_t gl_vbo;
9058 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9066 int surfacefirsttriangle;
9067 int surfacenumtriangles;
9068 int surfacefirstvertex;
9069 int surfaceendvertex;
9070 int surfacenumvertices;
9071 int batchnumsurfaces = texturenumsurfaces;
9072 int batchnumvertices;
9073 int batchnumtriangles;
9077 qboolean dynamicvertex;
9080 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9083 q3shaderinfo_deform_t *deform;
9084 const msurface_t *surface, *firstsurface;
9085 r_vertexmesh_t *vertexmesh;
9086 if (!texturenumsurfaces)
9088 // find vertex range of this surface batch
9090 firstsurface = texturesurfacelist[0];
9091 firsttriangle = firstsurface->num_firsttriangle;
9092 batchnumvertices = 0;
9093 batchnumtriangles = 0;
9094 firstvertex = endvertex = firstsurface->num_firstvertex;
9095 for (i = 0;i < texturenumsurfaces;i++)
9097 surface = texturesurfacelist[i];
9098 if (surface != firstsurface + i)
9100 surfacefirstvertex = surface->num_firstvertex;
9101 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9102 surfacenumvertices = surface->num_vertices;
9103 surfacenumtriangles = surface->num_triangles;
9104 if (firstvertex > surfacefirstvertex)
9105 firstvertex = surfacefirstvertex;
9106 if (endvertex < surfaceendvertex)
9107 endvertex = surfaceendvertex;
9108 batchnumvertices += surfacenumvertices;
9109 batchnumtriangles += surfacenumtriangles;
9112 r_refdef.stats[r_stat_batch_batches]++;
9114 r_refdef.stats[r_stat_batch_withgaps]++;
9115 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9116 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9117 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9119 // we now know the vertex range used, and if there are any gaps in it
9120 rsurface.batchfirstvertex = firstvertex;
9121 rsurface.batchnumvertices = endvertex - firstvertex;
9122 rsurface.batchfirsttriangle = firsttriangle;
9123 rsurface.batchnumtriangles = batchnumtriangles;
9125 // this variable holds flags for which properties have been updated that
9126 // may require regenerating vertexmesh array...
9129 // check if any dynamic vertex processing must occur
9130 dynamicvertex = false;
9132 // a cvar to force the dynamic vertex path to be taken, for debugging
9133 if (r_batch_debugdynamicvertexpath.integer)
9137 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9138 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9139 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9140 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9142 dynamicvertex = true;
9145 // if there is a chance of animated vertex colors, it's a dynamic batch
9146 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9150 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9151 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9152 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9153 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9155 dynamicvertex = true;
9156 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9159 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9161 switch (deform->deform)
9164 case Q3DEFORM_PROJECTIONSHADOW:
9165 case Q3DEFORM_TEXT0:
9166 case Q3DEFORM_TEXT1:
9167 case Q3DEFORM_TEXT2:
9168 case Q3DEFORM_TEXT3:
9169 case Q3DEFORM_TEXT4:
9170 case Q3DEFORM_TEXT5:
9171 case Q3DEFORM_TEXT6:
9172 case Q3DEFORM_TEXT7:
9175 case Q3DEFORM_AUTOSPRITE:
9178 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9179 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9180 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9181 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9183 dynamicvertex = true;
9184 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9185 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9187 case Q3DEFORM_AUTOSPRITE2:
9190 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9191 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9192 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9193 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9195 dynamicvertex = true;
9196 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9197 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9199 case Q3DEFORM_NORMAL:
9202 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9203 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9204 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9205 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9207 dynamicvertex = true;
9208 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9209 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9212 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9213 break; // if wavefunc is a nop, ignore this transform
9216 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9217 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9218 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9219 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9221 dynamicvertex = true;
9222 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9223 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9225 case Q3DEFORM_BULGE:
9228 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9229 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9230 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9231 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9233 dynamicvertex = true;
9234 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9235 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9238 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9239 break; // if wavefunc is a nop, ignore this transform
9242 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9243 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9244 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9245 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9247 dynamicvertex = true;
9248 batchneed |= BATCHNEED_ARRAY_VERTEX;
9249 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9253 if (rsurface.texture->materialshaderpass)
9255 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9258 case Q3TCGEN_TEXTURE:
9260 case Q3TCGEN_LIGHTMAP:
9263 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9264 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9265 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9266 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9268 dynamicvertex = true;
9269 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9270 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9272 case Q3TCGEN_VECTOR:
9275 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9276 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9277 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9278 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9280 dynamicvertex = true;
9281 batchneed |= BATCHNEED_ARRAY_VERTEX;
9282 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9284 case Q3TCGEN_ENVIRONMENT:
9287 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9288 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9289 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9290 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9292 dynamicvertex = true;
9293 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9294 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9297 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9301 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9302 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9303 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9304 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9306 dynamicvertex = true;
9307 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9308 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9312 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9316 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9317 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9318 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9319 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9321 dynamicvertex = true;
9322 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9325 // when the model data has no vertex buffer (dynamic mesh), we need to
9327 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9328 batchneed |= BATCHNEED_NOGAPS;
9330 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9331 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9332 // we ensure this by treating the vertex batch as dynamic...
9333 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9337 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9338 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9339 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9340 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9342 dynamicvertex = true;
9347 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9348 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9349 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9350 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9351 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9352 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9353 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9354 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9357 // if needsupdate, we have to do a dynamic vertex batch for sure
9358 if (needsupdate & batchneed)
9362 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9363 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9364 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9365 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9367 dynamicvertex = true;
9370 // see if we need to build vertexmesh from arrays
9371 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9375 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9376 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9377 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9378 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9380 dynamicvertex = true;
9383 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9384 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9385 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9387 rsurface.batchvertex3f = rsurface.modelvertex3f;
9388 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9389 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9390 rsurface.batchsvector3f = rsurface.modelsvector3f;
9391 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9392 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9393 rsurface.batchtvector3f = rsurface.modeltvector3f;
9394 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9395 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9396 rsurface.batchnormal3f = rsurface.modelnormal3f;
9397 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9398 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9399 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9400 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9401 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9402 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9403 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9404 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9405 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9406 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9407 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9408 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9409 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9410 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9411 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9412 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9413 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9414 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9415 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9416 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9417 rsurface.batchelement3i = rsurface.modelelement3i;
9418 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9419 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9420 rsurface.batchelement3s = rsurface.modelelement3s;
9421 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9422 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9423 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9424 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9425 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9426 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9427 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9429 // if any dynamic vertex processing has to occur in software, we copy the
9430 // entire surface list together before processing to rebase the vertices
9431 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9433 // if any gaps exist and we do not have a static vertex buffer, we have to
9434 // copy the surface list together to avoid wasting upload bandwidth on the
9435 // vertices in the gaps.
9437 // if gaps exist and we have a static vertex buffer, we can choose whether
9438 // to combine the index buffer ranges into one dynamic index buffer or
9439 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9441 // in many cases the batch is reduced to one draw call.
9443 rsurface.batchmultidraw = false;
9444 rsurface.batchmultidrawnumsurfaces = 0;
9445 rsurface.batchmultidrawsurfacelist = NULL;
9449 // static vertex data, just set pointers...
9450 rsurface.batchgeneratedvertex = false;
9451 // if there are gaps, we want to build a combined index buffer,
9452 // otherwise use the original static buffer with an appropriate offset
9455 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9456 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9457 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9458 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9459 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9461 rsurface.batchmultidraw = true;
9462 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9463 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9466 // build a new triangle elements array for this batch
9467 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9468 rsurface.batchfirsttriangle = 0;
9470 for (i = 0;i < texturenumsurfaces;i++)
9472 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9473 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9474 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9475 numtriangles += surfacenumtriangles;
9477 rsurface.batchelement3i_indexbuffer = NULL;
9478 rsurface.batchelement3i_bufferoffset = 0;
9479 rsurface.batchelement3s = NULL;
9480 rsurface.batchelement3s_indexbuffer = NULL;
9481 rsurface.batchelement3s_bufferoffset = 0;
9482 if (endvertex <= 65536)
9484 // make a 16bit (unsigned short) index array if possible
9485 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9486 for (i = 0;i < numtriangles*3;i++)
9487 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9489 // upload buffer data for the copytriangles batch
9490 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9492 if (rsurface.batchelement3s)
9493 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9494 else if (rsurface.batchelement3i)
9495 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9500 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9501 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9502 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9503 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9508 // something needs software processing, do it for real...
9509 // we only directly handle separate array data in this case and then
9510 // generate interleaved data if needed...
9511 rsurface.batchgeneratedvertex = true;
9512 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9513 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9514 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9515 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9517 // now copy the vertex data into a combined array and make an index array
9518 // (this is what Quake3 does all the time)
9519 // we also apply any skeletal animation here that would have been done in
9520 // the vertex shader, because most of the dynamic vertex animation cases
9521 // need actual vertex positions and normals
9522 //if (dynamicvertex)
9524 rsurface.batchvertexmesh = NULL;
9525 rsurface.batchvertexmesh_vertexbuffer = NULL;
9526 rsurface.batchvertexmesh_bufferoffset = 0;
9527 rsurface.batchvertex3f = NULL;
9528 rsurface.batchvertex3f_vertexbuffer = NULL;
9529 rsurface.batchvertex3f_bufferoffset = 0;
9530 rsurface.batchsvector3f = NULL;
9531 rsurface.batchsvector3f_vertexbuffer = NULL;
9532 rsurface.batchsvector3f_bufferoffset = 0;
9533 rsurface.batchtvector3f = NULL;
9534 rsurface.batchtvector3f_vertexbuffer = NULL;
9535 rsurface.batchtvector3f_bufferoffset = 0;
9536 rsurface.batchnormal3f = NULL;
9537 rsurface.batchnormal3f_vertexbuffer = NULL;
9538 rsurface.batchnormal3f_bufferoffset = 0;
9539 rsurface.batchlightmapcolor4f = NULL;
9540 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9541 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9542 rsurface.batchtexcoordtexture2f = NULL;
9543 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9544 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9545 rsurface.batchtexcoordlightmap2f = NULL;
9546 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9547 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9548 rsurface.batchskeletalindex4ub = NULL;
9549 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9550 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9551 rsurface.batchskeletalweight4ub = NULL;
9552 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9553 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9554 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9555 rsurface.batchelement3i_indexbuffer = NULL;
9556 rsurface.batchelement3i_bufferoffset = 0;
9557 rsurface.batchelement3s = NULL;
9558 rsurface.batchelement3s_indexbuffer = NULL;
9559 rsurface.batchelement3s_bufferoffset = 0;
9560 rsurface.batchskeletaltransform3x4buffer = NULL;
9561 rsurface.batchskeletaltransform3x4offset = 0;
9562 rsurface.batchskeletaltransform3x4size = 0;
9563 // we'll only be setting up certain arrays as needed
9564 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9565 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9566 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9567 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9568 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9569 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9570 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9572 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9573 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9575 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9576 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9577 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9578 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9579 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9580 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9581 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9583 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9584 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9588 for (i = 0;i < texturenumsurfaces;i++)
9590 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9591 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9592 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9593 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9594 // copy only the data requested
9595 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9596 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9597 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9599 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9601 if (rsurface.batchvertex3f)
9602 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9604 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9606 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9608 if (rsurface.modelnormal3f)
9609 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9611 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9613 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9615 if (rsurface.modelsvector3f)
9617 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9618 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9622 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9623 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9626 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9628 if (rsurface.modellightmapcolor4f)
9629 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9631 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9633 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9635 if (rsurface.modeltexcoordtexture2f)
9636 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9638 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9640 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9642 if (rsurface.modeltexcoordlightmap2f)
9643 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9645 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9647 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9649 if (rsurface.modelskeletalindex4ub)
9651 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9652 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9656 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9657 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9658 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9659 for (j = 0;j < surfacenumvertices;j++)
9664 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9665 numvertices += surfacenumvertices;
9666 numtriangles += surfacenumtriangles;
9669 // generate a 16bit index array as well if possible
9670 // (in general, dynamic batches fit)
9671 if (numvertices <= 65536)
9673 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9674 for (i = 0;i < numtriangles*3;i++)
9675 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9678 // since we've copied everything, the batch now starts at 0
9679 rsurface.batchfirstvertex = 0;
9680 rsurface.batchnumvertices = batchnumvertices;
9681 rsurface.batchfirsttriangle = 0;
9682 rsurface.batchnumtriangles = batchnumtriangles;
9685 // apply skeletal animation that would have been done in the vertex shader
9686 if (rsurface.batchskeletaltransform3x4)
9688 const unsigned char *si;
9689 const unsigned char *sw;
9691 const float *b = rsurface.batchskeletaltransform3x4;
9692 float *vp, *vs, *vt, *vn;
9694 float m[3][4], n[3][4];
9695 float tp[3], ts[3], tt[3], tn[3];
9696 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9697 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9698 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9699 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9700 si = rsurface.batchskeletalindex4ub;
9701 sw = rsurface.batchskeletalweight4ub;
9702 vp = rsurface.batchvertex3f;
9703 vs = rsurface.batchsvector3f;
9704 vt = rsurface.batchtvector3f;
9705 vn = rsurface.batchnormal3f;
9706 memset(m[0], 0, sizeof(m));
9707 memset(n[0], 0, sizeof(n));
9708 for (i = 0;i < batchnumvertices;i++)
9710 t[0] = b + si[0]*12;
9713 // common case - only one matrix
9727 else if (sw[2] + sw[3])
9730 t[1] = b + si[1]*12;
9731 t[2] = b + si[2]*12;
9732 t[3] = b + si[3]*12;
9733 w[0] = sw[0] * (1.0f / 255.0f);
9734 w[1] = sw[1] * (1.0f / 255.0f);
9735 w[2] = sw[2] * (1.0f / 255.0f);
9736 w[3] = sw[3] * (1.0f / 255.0f);
9737 // blend the matrices
9738 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9739 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9740 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9741 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9742 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9743 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9744 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9745 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9746 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9747 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9748 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9749 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9754 t[1] = b + si[1]*12;
9755 w[0] = sw[0] * (1.0f / 255.0f);
9756 w[1] = sw[1] * (1.0f / 255.0f);
9757 // blend the matrices
9758 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9759 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9760 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9761 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9762 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9763 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9764 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9765 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9766 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9767 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9768 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9769 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9773 // modify the vertex
9775 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9776 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9777 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9781 // the normal transformation matrix is a set of cross products...
9782 CrossProduct(m[1], m[2], n[0]);
9783 CrossProduct(m[2], m[0], n[1]);
9784 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9786 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9787 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9788 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9789 VectorNormalize(vn);
9794 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9795 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9796 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9797 VectorNormalize(vs);
9800 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9801 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9802 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9803 VectorNormalize(vt);
9808 rsurface.batchskeletaltransform3x4 = NULL;
9809 rsurface.batchskeletalnumtransforms = 0;
9812 // q1bsp surfaces rendered in vertex color mode have to have colors
9813 // calculated based on lightstyles
9814 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9816 // generate color arrays for the surfaces in this list
9821 const unsigned char *lm;
9822 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9823 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9824 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9826 for (i = 0;i < texturenumsurfaces;i++)
9828 surface = texturesurfacelist[i];
9829 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9830 surfacenumvertices = surface->num_vertices;
9831 if (surface->lightmapinfo->samples)
9833 for (j = 0;j < surfacenumvertices;j++)
9835 lm = surface->lightmapinfo->samples + offsets[j];
9836 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9837 VectorScale(lm, scale, c);
9838 if (surface->lightmapinfo->styles[1] != 255)
9840 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9842 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9843 VectorMA(c, scale, lm, c);
9844 if (surface->lightmapinfo->styles[2] != 255)
9847 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9848 VectorMA(c, scale, lm, c);
9849 if (surface->lightmapinfo->styles[3] != 255)
9852 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9853 VectorMA(c, scale, lm, c);
9860 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);
9866 for (j = 0;j < surfacenumvertices;j++)
9868 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9875 // if vertices are deformed (sprite flares and things in maps, possibly
9876 // water waves, bulges and other deformations), modify the copied vertices
9878 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9881 switch (deform->deform)
9884 case Q3DEFORM_PROJECTIONSHADOW:
9885 case Q3DEFORM_TEXT0:
9886 case Q3DEFORM_TEXT1:
9887 case Q3DEFORM_TEXT2:
9888 case Q3DEFORM_TEXT3:
9889 case Q3DEFORM_TEXT4:
9890 case Q3DEFORM_TEXT5:
9891 case Q3DEFORM_TEXT6:
9892 case Q3DEFORM_TEXT7:
9895 case Q3DEFORM_AUTOSPRITE:
9896 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9897 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9898 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9899 VectorNormalize(newforward);
9900 VectorNormalize(newright);
9901 VectorNormalize(newup);
9902 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9903 // rsurface.batchvertex3f_vertexbuffer = NULL;
9904 // rsurface.batchvertex3f_bufferoffset = 0;
9905 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9906 // rsurface.batchsvector3f_vertexbuffer = NULL;
9907 // rsurface.batchsvector3f_bufferoffset = 0;
9908 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9909 // rsurface.batchtvector3f_vertexbuffer = NULL;
9910 // rsurface.batchtvector3f_bufferoffset = 0;
9911 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9912 // rsurface.batchnormal3f_vertexbuffer = NULL;
9913 // rsurface.batchnormal3f_bufferoffset = 0;
9914 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9915 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9916 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9917 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9918 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);
9919 // a single autosprite surface can contain multiple sprites...
9920 for (j = 0;j < batchnumvertices - 3;j += 4)
9922 VectorClear(center);
9923 for (i = 0;i < 4;i++)
9924 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9925 VectorScale(center, 0.25f, center);
9926 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9927 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9928 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9929 for (i = 0;i < 4;i++)
9931 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9932 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9935 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9936 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9937 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);
9939 case Q3DEFORM_AUTOSPRITE2:
9940 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9941 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9942 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9943 VectorNormalize(newforward);
9944 VectorNormalize(newright);
9945 VectorNormalize(newup);
9946 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9947 // rsurface.batchvertex3f_vertexbuffer = NULL;
9948 // rsurface.batchvertex3f_bufferoffset = 0;
9950 const float *v1, *v2;
9960 memset(shortest, 0, sizeof(shortest));
9961 // a single autosprite surface can contain multiple sprites...
9962 for (j = 0;j < batchnumvertices - 3;j += 4)
9964 VectorClear(center);
9965 for (i = 0;i < 4;i++)
9966 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9967 VectorScale(center, 0.25f, center);
9968 // find the two shortest edges, then use them to define the
9969 // axis vectors for rotating around the central axis
9970 for (i = 0;i < 6;i++)
9972 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9973 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9974 l = VectorDistance2(v1, v2);
9975 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9977 l += (1.0f / 1024.0f);
9978 if (shortest[0].length2 > l || i == 0)
9980 shortest[1] = shortest[0];
9981 shortest[0].length2 = l;
9982 shortest[0].v1 = v1;
9983 shortest[0].v2 = v2;
9985 else if (shortest[1].length2 > l || i == 1)
9987 shortest[1].length2 = l;
9988 shortest[1].v1 = v1;
9989 shortest[1].v2 = v2;
9992 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9993 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9994 // this calculates the right vector from the shortest edge
9995 // and the up vector from the edge midpoints
9996 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9997 VectorNormalize(right);
9998 VectorSubtract(end, start, up);
9999 VectorNormalize(up);
10000 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10001 VectorSubtract(rsurface.localvieworigin, center, forward);
10002 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10003 VectorNegate(forward, forward);
10004 VectorReflect(forward, 0, up, forward);
10005 VectorNormalize(forward);
10006 CrossProduct(up, forward, newright);
10007 VectorNormalize(newright);
10008 // rotate the quad around the up axis vector, this is made
10009 // especially easy by the fact we know the quad is flat,
10010 // so we only have to subtract the center position and
10011 // measure distance along the right vector, and then
10012 // multiply that by the newright vector and add back the
10014 // we also need to subtract the old position to undo the
10015 // displacement from the center, which we do with a
10016 // DotProduct, the subtraction/addition of center is also
10017 // optimized into DotProducts here
10018 l = DotProduct(right, center);
10019 for (i = 0;i < 4;i++)
10021 v1 = rsurface.batchvertex3f + 3*(j+i);
10022 f = DotProduct(right, v1) - l;
10023 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10027 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10029 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10030 // rsurface.batchnormal3f_vertexbuffer = NULL;
10031 // rsurface.batchnormal3f_bufferoffset = 0;
10032 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10034 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10036 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10037 // rsurface.batchsvector3f_vertexbuffer = NULL;
10038 // rsurface.batchsvector3f_bufferoffset = 0;
10039 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10040 // rsurface.batchtvector3f_vertexbuffer = NULL;
10041 // rsurface.batchtvector3f_bufferoffset = 0;
10042 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);
10045 case Q3DEFORM_NORMAL:
10046 // deform the normals to make reflections wavey
10047 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10048 rsurface.batchnormal3f_vertexbuffer = NULL;
10049 rsurface.batchnormal3f_bufferoffset = 0;
10050 for (j = 0;j < batchnumvertices;j++)
10053 float *normal = rsurface.batchnormal3f + 3*j;
10054 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10055 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10056 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10057 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10058 VectorNormalize(normal);
10060 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10062 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10063 // rsurface.batchsvector3f_vertexbuffer = NULL;
10064 // rsurface.batchsvector3f_bufferoffset = 0;
10065 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10066 // rsurface.batchtvector3f_vertexbuffer = NULL;
10067 // rsurface.batchtvector3f_bufferoffset = 0;
10068 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);
10071 case Q3DEFORM_WAVE:
10072 // deform vertex array to make wavey water and flags and such
10073 waveparms[0] = deform->waveparms[0];
10074 waveparms[1] = deform->waveparms[1];
10075 waveparms[2] = deform->waveparms[2];
10076 waveparms[3] = deform->waveparms[3];
10077 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10078 break; // if wavefunc is a nop, don't make a dynamic vertex array
10079 // this is how a divisor of vertex influence on deformation
10080 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10081 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10082 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10083 // rsurface.batchvertex3f_vertexbuffer = NULL;
10084 // rsurface.batchvertex3f_bufferoffset = 0;
10085 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10086 // rsurface.batchnormal3f_vertexbuffer = NULL;
10087 // rsurface.batchnormal3f_bufferoffset = 0;
10088 for (j = 0;j < batchnumvertices;j++)
10090 // if the wavefunc depends on time, evaluate it per-vertex
10093 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10094 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10096 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10098 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10099 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10100 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10102 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10103 // rsurface.batchsvector3f_vertexbuffer = NULL;
10104 // rsurface.batchsvector3f_bufferoffset = 0;
10105 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10106 // rsurface.batchtvector3f_vertexbuffer = NULL;
10107 // rsurface.batchtvector3f_bufferoffset = 0;
10108 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);
10111 case Q3DEFORM_BULGE:
10112 // deform vertex array to make the surface have moving bulges
10113 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10114 // rsurface.batchvertex3f_vertexbuffer = NULL;
10115 // rsurface.batchvertex3f_bufferoffset = 0;
10116 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10117 // rsurface.batchnormal3f_vertexbuffer = NULL;
10118 // rsurface.batchnormal3f_bufferoffset = 0;
10119 for (j = 0;j < batchnumvertices;j++)
10121 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10122 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10124 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10125 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10126 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10128 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10129 // rsurface.batchsvector3f_vertexbuffer = NULL;
10130 // rsurface.batchsvector3f_bufferoffset = 0;
10131 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10132 // rsurface.batchtvector3f_vertexbuffer = NULL;
10133 // rsurface.batchtvector3f_bufferoffset = 0;
10134 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);
10137 case Q3DEFORM_MOVE:
10138 // deform vertex array
10139 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10140 break; // if wavefunc is a nop, don't make a dynamic vertex array
10141 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10142 VectorScale(deform->parms, scale, waveparms);
10143 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10144 // rsurface.batchvertex3f_vertexbuffer = NULL;
10145 // rsurface.batchvertex3f_bufferoffset = 0;
10146 for (j = 0;j < batchnumvertices;j++)
10147 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10152 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10154 // generate texcoords based on the chosen texcoord source
10155 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10158 case Q3TCGEN_TEXTURE:
10160 case Q3TCGEN_LIGHTMAP:
10161 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10162 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10163 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10164 if (rsurface.batchtexcoordlightmap2f)
10165 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10167 case Q3TCGEN_VECTOR:
10168 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10169 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10170 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10171 for (j = 0;j < batchnumvertices;j++)
10173 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10174 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10177 case Q3TCGEN_ENVIRONMENT:
10178 // make environment reflections using a spheremap
10179 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10180 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10181 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10182 for (j = 0;j < batchnumvertices;j++)
10184 // identical to Q3A's method, but executed in worldspace so
10185 // carried models can be shiny too
10187 float viewer[3], d, reflected[3], worldreflected[3];
10189 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10190 // VectorNormalize(viewer);
10192 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10194 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10195 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10196 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10197 // note: this is proportinal to viewer, so we can normalize later
10199 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10200 VectorNormalize(worldreflected);
10202 // note: this sphere map only uses world x and z!
10203 // so positive and negative y will LOOK THE SAME.
10204 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10205 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10209 // the only tcmod that needs software vertex processing is turbulent, so
10210 // check for it here and apply the changes if needed
10211 // and we only support that as the first one
10212 // (handling a mixture of turbulent and other tcmods would be problematic
10213 // without punting it entirely to a software path)
10214 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10216 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10217 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10218 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10219 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10220 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10221 for (j = 0;j < batchnumvertices;j++)
10223 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);
10224 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10229 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10231 // convert the modified arrays to vertex structs
10232 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10233 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10234 // rsurface.batchvertexmesh_bufferoffset = 0;
10235 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10236 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10237 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10238 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10239 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10240 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10241 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10243 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10245 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10246 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10249 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10250 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10251 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10252 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10253 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10254 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10255 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10256 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10257 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10258 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10260 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10262 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10263 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10268 // upload buffer data for the dynamic batch
10269 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10271 if (rsurface.batchvertexmesh)
10272 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10275 if (rsurface.batchvertex3f)
10276 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10277 if (rsurface.batchsvector3f)
10278 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10279 if (rsurface.batchtvector3f)
10280 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10281 if (rsurface.batchnormal3f)
10282 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10283 if (rsurface.batchlightmapcolor4f)
10284 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10285 if (rsurface.batchtexcoordtexture2f)
10286 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10287 if (rsurface.batchtexcoordlightmap2f)
10288 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10289 if (rsurface.batchskeletalindex4ub)
10290 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10291 if (rsurface.batchskeletalweight4ub)
10292 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10294 if (rsurface.batchelement3s)
10295 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10296 else if (rsurface.batchelement3i)
10297 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10301 void RSurf_DrawBatch(void)
10303 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10304 // through the pipeline, killing it earlier in the pipeline would have
10305 // per-surface overhead rather than per-batch overhead, so it's best to
10306 // reject it here, before it hits glDraw.
10307 if (rsurface.batchnumtriangles == 0)
10310 // batch debugging code
10311 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10317 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10318 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10321 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10323 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10325 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10326 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);
10333 if (rsurface.batchmultidraw)
10335 // issue multiple draws rather than copying index data
10336 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10337 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10338 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10339 for (i = 0;i < numsurfaces;)
10341 // combine consecutive surfaces as one draw
10342 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10343 if (surfacelist[j] != surfacelist[k] + 1)
10345 firstvertex = surfacelist[i]->num_firstvertex;
10346 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10347 firsttriangle = surfacelist[i]->num_firsttriangle;
10348 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10349 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);
10355 // there is only one consecutive run of index data (may have been combined)
10356 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);
10360 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10362 // pick the closest matching water plane
10363 int planeindex, vertexindex, bestplaneindex = -1;
10367 r_waterstate_waterplane_t *p;
10368 qboolean prepared = false;
10370 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10372 if(p->camera_entity != rsurface.texture->camera_entity)
10377 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10379 if(rsurface.batchnumvertices == 0)
10382 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10384 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10385 d += fabs(PlaneDiff(vert, &p->plane));
10387 if (bestd > d || bestplaneindex < 0)
10390 bestplaneindex = planeindex;
10393 return bestplaneindex;
10394 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10395 // this situation though, as it might be better to render single larger
10396 // batches with useless stuff (backface culled for example) than to
10397 // render multiple smaller batches
10400 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10403 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10404 rsurface.passcolor4f_vertexbuffer = 0;
10405 rsurface.passcolor4f_bufferoffset = 0;
10406 for (i = 0;i < rsurface.batchnumvertices;i++)
10407 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10410 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10417 if (rsurface.passcolor4f)
10419 // generate color arrays
10420 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10421 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10422 rsurface.passcolor4f_vertexbuffer = 0;
10423 rsurface.passcolor4f_bufferoffset = 0;
10424 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)
10426 f = RSurf_FogVertex(v);
10435 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10436 rsurface.passcolor4f_vertexbuffer = 0;
10437 rsurface.passcolor4f_bufferoffset = 0;
10438 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10440 f = RSurf_FogVertex(v);
10449 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10456 if (!rsurface.passcolor4f)
10458 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10459 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10460 rsurface.passcolor4f_vertexbuffer = 0;
10461 rsurface.passcolor4f_bufferoffset = 0;
10462 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)
10464 f = RSurf_FogVertex(v);
10465 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10466 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10467 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10472 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10477 if (!rsurface.passcolor4f)
10479 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10480 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10481 rsurface.passcolor4f_vertexbuffer = 0;
10482 rsurface.passcolor4f_bufferoffset = 0;
10483 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10492 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10497 if (!rsurface.passcolor4f)
10499 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10500 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10501 rsurface.passcolor4f_vertexbuffer = 0;
10502 rsurface.passcolor4f_bufferoffset = 0;
10503 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10505 c2[0] = c[0] + r_refdef.scene.ambient;
10506 c2[1] = c[1] + r_refdef.scene.ambient;
10507 c2[2] = c[2] + r_refdef.scene.ambient;
10512 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10515 rsurface.passcolor4f = NULL;
10516 rsurface.passcolor4f_vertexbuffer = 0;
10517 rsurface.passcolor4f_bufferoffset = 0;
10518 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10519 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10520 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10521 GL_Color(r, g, b, a);
10522 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10523 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10524 R_Mesh_TexMatrix(0, NULL);
10528 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10530 // TODO: optimize applyfog && applycolor case
10531 // just apply fog if necessary, and tint the fog color array if necessary
10532 rsurface.passcolor4f = NULL;
10533 rsurface.passcolor4f_vertexbuffer = 0;
10534 rsurface.passcolor4f_bufferoffset = 0;
10535 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10536 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10537 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10538 GL_Color(r, g, b, a);
10542 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10545 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10546 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10547 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10548 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10549 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10550 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10551 GL_Color(r, g, b, a);
10555 static void RSurf_DrawBatch_GL11_ClampColor(void)
10560 if (!rsurface.passcolor4f)
10562 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10564 c2[0] = bound(0.0f, c1[0], 1.0f);
10565 c2[1] = bound(0.0f, c1[1], 1.0f);
10566 c2[2] = bound(0.0f, c1[2], 1.0f);
10567 c2[3] = bound(0.0f, c1[3], 1.0f);
10571 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10581 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10582 rsurface.passcolor4f_vertexbuffer = 0;
10583 rsurface.passcolor4f_bufferoffset = 0;
10584 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)
10586 f = -DotProduct(r_refdef.view.forward, n);
10588 f = f * 0.85 + 0.15; // work around so stuff won't get black
10589 f *= r_refdef.lightmapintensity;
10590 Vector4Set(c, f, f, f, 1);
10594 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10596 RSurf_DrawBatch_GL11_ApplyFakeLight();
10597 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10598 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10599 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10600 GL_Color(r, g, b, a);
10604 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10612 vec3_t ambientcolor;
10613 vec3_t diffusecolor;
10617 VectorCopy(rsurface.modellight_lightdir, lightdir);
10618 f = 0.5f * r_refdef.lightmapintensity;
10619 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10620 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10621 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10622 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10623 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10624 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10626 if (VectorLength2(diffusecolor) > 0)
10628 // q3-style directional shading
10629 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10630 rsurface.passcolor4f_vertexbuffer = 0;
10631 rsurface.passcolor4f_bufferoffset = 0;
10632 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)
10634 if ((f = DotProduct(n, lightdir)) > 0)
10635 VectorMA(ambientcolor, f, diffusecolor, c);
10637 VectorCopy(ambientcolor, c);
10644 *applycolor = false;
10648 *r = ambientcolor[0];
10649 *g = ambientcolor[1];
10650 *b = ambientcolor[2];
10651 rsurface.passcolor4f = NULL;
10652 rsurface.passcolor4f_vertexbuffer = 0;
10653 rsurface.passcolor4f_bufferoffset = 0;
10657 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10659 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10660 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10661 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10662 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10663 GL_Color(r, g, b, a);
10667 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10675 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10676 rsurface.passcolor4f_vertexbuffer = 0;
10677 rsurface.passcolor4f_bufferoffset = 0;
10679 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10681 f = 1 - RSurf_FogVertex(v);
10689 void RSurf_SetupDepthAndCulling(void)
10691 // submodels are biased to avoid z-fighting with world surfaces that they
10692 // may be exactly overlapping (avoids z-fighting artifacts on certain
10693 // doors and things in Quake maps)
10694 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10695 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10696 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10697 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10700 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10702 // transparent sky would be ridiculous
10703 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10705 R_SetupShader_Generic_NoTexture(false, false);
10706 skyrenderlater = true;
10707 RSurf_SetupDepthAndCulling();
10708 GL_DepthMask(true);
10709 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10710 // skymasking on them, and Quake3 never did sky masking (unlike
10711 // software Quake and software Quake2), so disable the sky masking
10712 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10713 // and skymasking also looks very bad when noclipping outside the
10714 // level, so don't use it then either.
10715 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10717 R_Mesh_ResetTextureState();
10718 if (skyrendermasked)
10720 R_SetupShader_DepthOrShadow(false, false, false);
10721 // depth-only (masking)
10722 GL_ColorMask(0,0,0,0);
10723 // just to make sure that braindead drivers don't draw
10724 // anything despite that colormask...
10725 GL_BlendFunc(GL_ZERO, GL_ONE);
10726 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10727 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10731 R_SetupShader_Generic_NoTexture(false, false);
10733 GL_BlendFunc(GL_ONE, GL_ZERO);
10734 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10735 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10736 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10739 if (skyrendermasked)
10740 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10742 R_Mesh_ResetTextureState();
10743 GL_Color(1, 1, 1, 1);
10746 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10747 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10748 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10750 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10754 // render screenspace normalmap to texture
10755 GL_DepthMask(true);
10756 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10761 // bind lightmap texture
10763 // water/refraction/reflection/camera surfaces have to be handled specially
10764 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10766 int start, end, startplaneindex;
10767 for (start = 0;start < texturenumsurfaces;start = end)
10769 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10770 if(startplaneindex < 0)
10772 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10773 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10777 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10779 // now that we have a batch using the same planeindex, render it
10780 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10782 // render water or distortion background
10783 GL_DepthMask(true);
10784 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10786 // blend surface on top
10787 GL_DepthMask(false);
10788 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10791 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10793 // render surface with reflection texture as input
10794 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10795 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10802 // render surface batch normally
10803 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10804 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10808 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10810 // OpenGL 1.3 path - anything not completely ancient
10811 qboolean applycolor;
10814 const texturelayer_t *layer;
10815 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10816 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10818 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10821 int layertexrgbscale;
10822 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10824 if (layerindex == 0)
10825 GL_AlphaTest(true);
10828 GL_AlphaTest(false);
10829 GL_DepthFunc(GL_EQUAL);
10832 GL_DepthMask(layer->depthmask && writedepth);
10833 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10834 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10836 layertexrgbscale = 4;
10837 VectorScale(layer->color, 0.25f, layercolor);
10839 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10841 layertexrgbscale = 2;
10842 VectorScale(layer->color, 0.5f, layercolor);
10846 layertexrgbscale = 1;
10847 VectorScale(layer->color, 1.0f, layercolor);
10849 layercolor[3] = layer->color[3];
10850 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10851 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10852 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10853 switch (layer->type)
10855 case TEXTURELAYERTYPE_LITTEXTURE:
10856 // single-pass lightmapped texture with 2x rgbscale
10857 R_Mesh_TexBind(0, r_texture_white);
10858 R_Mesh_TexMatrix(0, NULL);
10859 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10860 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10861 R_Mesh_TexBind(1, layer->texture);
10862 R_Mesh_TexMatrix(1, &layer->texmatrix);
10863 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10864 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10865 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10866 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10867 else if (FAKELIGHT_ENABLED)
10868 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10869 else if (rsurface.uselightmaptexture)
10870 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10872 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10874 case TEXTURELAYERTYPE_TEXTURE:
10875 // singletexture unlit texture with transparency support
10876 R_Mesh_TexBind(0, layer->texture);
10877 R_Mesh_TexMatrix(0, &layer->texmatrix);
10878 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10879 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10880 R_Mesh_TexBind(1, 0);
10881 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10882 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10884 case TEXTURELAYERTYPE_FOG:
10885 // singletexture fogging
10886 if (layer->texture)
10888 R_Mesh_TexBind(0, layer->texture);
10889 R_Mesh_TexMatrix(0, &layer->texmatrix);
10890 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10891 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10895 R_Mesh_TexBind(0, 0);
10896 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10898 R_Mesh_TexBind(1, 0);
10899 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10900 // generate a color array for the fog pass
10901 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10902 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10906 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10909 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10911 GL_DepthFunc(GL_LEQUAL);
10912 GL_AlphaTest(false);
10916 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10918 // OpenGL 1.1 - crusty old voodoo path
10921 const texturelayer_t *layer;
10922 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10923 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10925 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10927 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10929 if (layerindex == 0)
10930 GL_AlphaTest(true);
10933 GL_AlphaTest(false);
10934 GL_DepthFunc(GL_EQUAL);
10937 GL_DepthMask(layer->depthmask && writedepth);
10938 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10939 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10940 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10941 switch (layer->type)
10943 case TEXTURELAYERTYPE_LITTEXTURE:
10944 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10946 // two-pass lit texture with 2x rgbscale
10947 // first the lightmap pass
10948 R_Mesh_TexBind(0, r_texture_white);
10949 R_Mesh_TexMatrix(0, NULL);
10950 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10951 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10952 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10953 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10954 else if (FAKELIGHT_ENABLED)
10955 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10956 else if (rsurface.uselightmaptexture)
10957 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10959 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10960 // then apply the texture to it
10961 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10962 R_Mesh_TexBind(0, layer->texture);
10963 R_Mesh_TexMatrix(0, &layer->texmatrix);
10964 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10965 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10966 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);
10970 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10971 R_Mesh_TexBind(0, layer->texture);
10972 R_Mesh_TexMatrix(0, &layer->texmatrix);
10973 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10974 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10975 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10976 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);
10977 else if (FAKELIGHT_ENABLED)
10978 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);
10980 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);
10983 case TEXTURELAYERTYPE_TEXTURE:
10984 // singletexture unlit texture with transparency support
10985 R_Mesh_TexBind(0, layer->texture);
10986 R_Mesh_TexMatrix(0, &layer->texmatrix);
10987 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10988 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10989 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);
10991 case TEXTURELAYERTYPE_FOG:
10992 // singletexture fogging
10993 if (layer->texture)
10995 R_Mesh_TexBind(0, layer->texture);
10996 R_Mesh_TexMatrix(0, &layer->texmatrix);
10997 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10998 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11002 R_Mesh_TexBind(0, 0);
11003 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11005 // generate a color array for the fog pass
11006 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11007 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11011 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11014 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11016 GL_DepthFunc(GL_LEQUAL);
11017 GL_AlphaTest(false);
11021 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11025 r_vertexgeneric_t *batchvertex;
11028 // R_Mesh_ResetTextureState();
11029 R_SetupShader_Generic_NoTexture(false, false);
11031 if(rsurface.texture && rsurface.texture->currentskinframe)
11033 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11034 c[3] *= rsurface.texture->currentalpha;
11044 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11046 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11047 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11048 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11051 // brighten it up (as texture value 127 means "unlit")
11052 c[0] *= 2 * r_refdef.view.colorscale;
11053 c[1] *= 2 * r_refdef.view.colorscale;
11054 c[2] *= 2 * r_refdef.view.colorscale;
11056 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11057 c[3] *= r_wateralpha.value;
11059 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11061 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11062 GL_DepthMask(false);
11064 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11066 GL_BlendFunc(GL_ONE, GL_ONE);
11067 GL_DepthMask(false);
11069 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11071 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11072 GL_DepthMask(false);
11074 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11076 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11077 GL_DepthMask(false);
11081 GL_BlendFunc(GL_ONE, GL_ZERO);
11082 GL_DepthMask(writedepth);
11085 if (r_showsurfaces.integer == 3)
11087 rsurface.passcolor4f = NULL;
11089 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11091 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11093 rsurface.passcolor4f = NULL;
11094 rsurface.passcolor4f_vertexbuffer = 0;
11095 rsurface.passcolor4f_bufferoffset = 0;
11097 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11099 qboolean applycolor = true;
11102 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11104 r_refdef.lightmapintensity = 1;
11105 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11106 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11108 else if (FAKELIGHT_ENABLED)
11110 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11112 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11113 RSurf_DrawBatch_GL11_ApplyFakeLight();
11114 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11118 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11120 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11121 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11122 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11125 if(!rsurface.passcolor4f)
11126 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11128 RSurf_DrawBatch_GL11_ApplyAmbient();
11129 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11130 if(r_refdef.fogenabled)
11131 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11132 RSurf_DrawBatch_GL11_ClampColor();
11134 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11135 R_SetupShader_Generic_NoTexture(false, false);
11138 else if (!r_refdef.view.showdebug)
11140 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11141 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11142 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11144 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11145 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11147 R_Mesh_PrepareVertices_Generic_Unlock();
11150 else if (r_showsurfaces.integer == 4)
11152 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11153 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11154 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11156 unsigned char d = (vi << 3) * (1.0f / 256.0f);
11157 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11158 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11160 R_Mesh_PrepareVertices_Generic_Unlock();
11163 else if (r_showsurfaces.integer == 2)
11166 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11167 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11168 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11170 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11171 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11172 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11173 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11174 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11175 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11176 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11178 R_Mesh_PrepareVertices_Generic_Unlock();
11179 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11183 int texturesurfaceindex;
11185 const msurface_t *surface;
11186 float surfacecolor4f[4];
11187 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11188 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11190 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11192 surface = texturesurfacelist[texturesurfaceindex];
11193 k = (int)(((size_t)surface) / sizeof(msurface_t));
11194 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11195 for (j = 0;j < surface->num_vertices;j++)
11197 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11198 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11202 R_Mesh_PrepareVertices_Generic_Unlock();
11207 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11210 RSurf_SetupDepthAndCulling();
11211 if (r_showsurfaces.integer)
11213 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11216 switch (vid.renderpath)
11218 case RENDERPATH_GL20:
11219 case RENDERPATH_D3D9:
11220 case RENDERPATH_D3D10:
11221 case RENDERPATH_D3D11:
11222 case RENDERPATH_SOFT:
11223 case RENDERPATH_GLES2:
11224 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11226 case RENDERPATH_GL13:
11227 case RENDERPATH_GLES1:
11228 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11230 case RENDERPATH_GL11:
11231 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11237 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11240 RSurf_SetupDepthAndCulling();
11241 if (r_showsurfaces.integer)
11243 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11246 switch (vid.renderpath)
11248 case RENDERPATH_GL20:
11249 case RENDERPATH_D3D9:
11250 case RENDERPATH_D3D10:
11251 case RENDERPATH_D3D11:
11252 case RENDERPATH_SOFT:
11253 case RENDERPATH_GLES2:
11254 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11256 case RENDERPATH_GL13:
11257 case RENDERPATH_GLES1:
11258 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11260 case RENDERPATH_GL11:
11261 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11267 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11270 int texturenumsurfaces, endsurface;
11271 texture_t *texture;
11272 const msurface_t *surface;
11273 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11275 // if the model is static it doesn't matter what value we give for
11276 // wantnormals and wanttangents, so this logic uses only rules applicable
11277 // to a model, knowing that they are meaningless otherwise
11278 if (ent == r_refdef.scene.worldentity)
11279 RSurf_ActiveWorldEntity();
11280 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11281 RSurf_ActiveModelEntity(ent, false, false, false);
11284 switch (vid.renderpath)
11286 case RENDERPATH_GL20:
11287 case RENDERPATH_D3D9:
11288 case RENDERPATH_D3D10:
11289 case RENDERPATH_D3D11:
11290 case RENDERPATH_SOFT:
11291 case RENDERPATH_GLES2:
11292 RSurf_ActiveModelEntity(ent, true, true, false);
11294 case RENDERPATH_GL11:
11295 case RENDERPATH_GL13:
11296 case RENDERPATH_GLES1:
11297 RSurf_ActiveModelEntity(ent, true, false, false);
11302 if (r_transparentdepthmasking.integer)
11304 qboolean setup = false;
11305 for (i = 0;i < numsurfaces;i = j)
11308 surface = rsurface.modelsurfaces + surfacelist[i];
11309 texture = surface->texture;
11310 rsurface.texture = R_GetCurrentTexture(texture);
11311 rsurface.lightmaptexture = NULL;
11312 rsurface.deluxemaptexture = NULL;
11313 rsurface.uselightmaptexture = false;
11314 // scan ahead until we find a different texture
11315 endsurface = min(i + 1024, numsurfaces);
11316 texturenumsurfaces = 0;
11317 texturesurfacelist[texturenumsurfaces++] = surface;
11318 for (;j < endsurface;j++)
11320 surface = rsurface.modelsurfaces + surfacelist[j];
11321 if (texture != surface->texture)
11323 texturesurfacelist[texturenumsurfaces++] = surface;
11325 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11327 // render the range of surfaces as depth
11331 GL_ColorMask(0,0,0,0);
11333 GL_DepthTest(true);
11334 GL_BlendFunc(GL_ONE, GL_ZERO);
11335 GL_DepthMask(true);
11336 // R_Mesh_ResetTextureState();
11338 RSurf_SetupDepthAndCulling();
11339 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11340 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11341 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11345 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11348 for (i = 0;i < numsurfaces;i = j)
11351 surface = rsurface.modelsurfaces + surfacelist[i];
11352 texture = surface->texture;
11353 rsurface.texture = R_GetCurrentTexture(texture);
11354 // scan ahead until we find a different texture
11355 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11356 texturenumsurfaces = 0;
11357 texturesurfacelist[texturenumsurfaces++] = surface;
11358 if(FAKELIGHT_ENABLED)
11360 rsurface.lightmaptexture = NULL;
11361 rsurface.deluxemaptexture = NULL;
11362 rsurface.uselightmaptexture = false;
11363 for (;j < endsurface;j++)
11365 surface = rsurface.modelsurfaces + surfacelist[j];
11366 if (texture != surface->texture)
11368 texturesurfacelist[texturenumsurfaces++] = surface;
11373 rsurface.lightmaptexture = surface->lightmaptexture;
11374 rsurface.deluxemaptexture = surface->deluxemaptexture;
11375 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11376 for (;j < endsurface;j++)
11378 surface = rsurface.modelsurfaces + surfacelist[j];
11379 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11381 texturesurfacelist[texturenumsurfaces++] = surface;
11384 // render the range of surfaces
11385 if (ent == r_refdef.scene.worldentity)
11386 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11388 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11390 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11393 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11395 // transparent surfaces get pushed off into the transparent queue
11396 int surfacelistindex;
11397 const msurface_t *surface;
11398 vec3_t tempcenter, center;
11399 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11401 surface = texturesurfacelist[surfacelistindex];
11402 if (r_transparent_sortsurfacesbynearest.integer)
11404 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11405 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11406 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11410 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11411 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11412 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11414 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11415 if (rsurface.entity->transparent_offset) // transparent offset
11417 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11418 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11419 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11421 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);
11425 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11427 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11429 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11431 RSurf_SetupDepthAndCulling();
11432 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11433 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11434 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11438 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11442 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11445 if (!rsurface.texture->currentnumlayers)
11447 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11448 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11450 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11452 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11453 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11454 else if (!rsurface.texture->currentnumlayers)
11456 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11458 // in the deferred case, transparent surfaces were queued during prepass
11459 if (!r_shadow_usingdeferredprepass)
11460 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11464 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11465 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11470 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11473 texture_t *texture;
11474 R_FrameData_SetMark();
11475 // break the surface list down into batches by texture and use of lightmapping
11476 for (i = 0;i < numsurfaces;i = j)
11479 // texture is the base texture pointer, rsurface.texture is the
11480 // current frame/skin the texture is directing us to use (for example
11481 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11482 // use skin 1 instead)
11483 texture = surfacelist[i]->texture;
11484 rsurface.texture = R_GetCurrentTexture(texture);
11485 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11487 // if this texture is not the kind we want, skip ahead to the next one
11488 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11492 if(FAKELIGHT_ENABLED || depthonly || prepass)
11494 rsurface.lightmaptexture = NULL;
11495 rsurface.deluxemaptexture = NULL;
11496 rsurface.uselightmaptexture = false;
11497 // simply scan ahead until we find a different texture or lightmap state
11498 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11503 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11504 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11505 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11506 // simply scan ahead until we find a different texture or lightmap state
11507 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11510 // render the range of surfaces
11511 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11513 R_FrameData_ReturnToMark();
11516 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11520 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11523 if (!rsurface.texture->currentnumlayers)
11525 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11526 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11528 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11530 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11531 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11532 else if (!rsurface.texture->currentnumlayers)
11534 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11536 // in the deferred case, transparent surfaces were queued during prepass
11537 if (!r_shadow_usingdeferredprepass)
11538 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11542 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11543 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11548 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11551 texture_t *texture;
11552 R_FrameData_SetMark();
11553 // break the surface list down into batches by texture and use of lightmapping
11554 for (i = 0;i < numsurfaces;i = j)
11557 // texture is the base texture pointer, rsurface.texture is the
11558 // current frame/skin the texture is directing us to use (for example
11559 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11560 // use skin 1 instead)
11561 texture = surfacelist[i]->texture;
11562 rsurface.texture = R_GetCurrentTexture(texture);
11563 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11565 // if this texture is not the kind we want, skip ahead to the next one
11566 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11570 if(FAKELIGHT_ENABLED || depthonly || prepass)
11572 rsurface.lightmaptexture = NULL;
11573 rsurface.deluxemaptexture = NULL;
11574 rsurface.uselightmaptexture = false;
11575 // simply scan ahead until we find a different texture or lightmap state
11576 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11581 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11582 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11583 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11584 // simply scan ahead until we find a different texture or lightmap state
11585 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11588 // render the range of surfaces
11589 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11591 R_FrameData_ReturnToMark();
11594 float locboxvertex3f[6*4*3] =
11596 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11597 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11598 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11599 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11600 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11601 1,0,0, 0,0,0, 0,1,0, 1,1,0
11604 unsigned short locboxelements[6*2*3] =
11609 12,13,14, 12,14,15,
11610 16,17,18, 16,18,19,
11614 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11617 cl_locnode_t *loc = (cl_locnode_t *)ent;
11619 float vertex3f[6*4*3];
11621 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11622 GL_DepthMask(false);
11623 GL_DepthRange(0, 1);
11624 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11625 GL_DepthTest(true);
11626 GL_CullFace(GL_NONE);
11627 R_EntityMatrix(&identitymatrix);
11629 // R_Mesh_ResetTextureState();
11631 i = surfacelist[0];
11632 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11633 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11634 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11635 surfacelist[0] < 0 ? 0.5f : 0.125f);
11637 if (VectorCompare(loc->mins, loc->maxs))
11639 VectorSet(size, 2, 2, 2);
11640 VectorMA(loc->mins, -0.5f, size, mins);
11644 VectorCopy(loc->mins, mins);
11645 VectorSubtract(loc->maxs, loc->mins, size);
11648 for (i = 0;i < 6*4*3;)
11649 for (j = 0;j < 3;j++, i++)
11650 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11652 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11653 R_SetupShader_Generic_NoTexture(false, false);
11654 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11657 void R_DrawLocs(void)
11660 cl_locnode_t *loc, *nearestloc;
11662 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11663 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11665 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11666 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11670 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11672 if (decalsystem->decals)
11673 Mem_Free(decalsystem->decals);
11674 memset(decalsystem, 0, sizeof(*decalsystem));
11677 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)
11680 tridecal_t *decals;
11683 // expand or initialize the system
11684 if (decalsystem->maxdecals <= decalsystem->numdecals)
11686 decalsystem_t old = *decalsystem;
11687 qboolean useshortelements;
11688 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11689 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11690 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)));
11691 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11692 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11693 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11694 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11695 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11696 if (decalsystem->numdecals)
11697 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11699 Mem_Free(old.decals);
11700 for (i = 0;i < decalsystem->maxdecals*3;i++)
11701 decalsystem->element3i[i] = i;
11702 if (useshortelements)
11703 for (i = 0;i < decalsystem->maxdecals*3;i++)
11704 decalsystem->element3s[i] = i;
11707 // grab a decal and search for another free slot for the next one
11708 decals = decalsystem->decals;
11709 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11710 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11712 decalsystem->freedecal = i;
11713 if (decalsystem->numdecals <= i)
11714 decalsystem->numdecals = i + 1;
11716 // initialize the decal
11718 decal->triangleindex = triangleindex;
11719 decal->surfaceindex = surfaceindex;
11720 decal->decalsequence = decalsequence;
11721 decal->color4f[0][0] = c0[0];
11722 decal->color4f[0][1] = c0[1];
11723 decal->color4f[0][2] = c0[2];
11724 decal->color4f[0][3] = 1;
11725 decal->color4f[1][0] = c1[0];
11726 decal->color4f[1][1] = c1[1];
11727 decal->color4f[1][2] = c1[2];
11728 decal->color4f[1][3] = 1;
11729 decal->color4f[2][0] = c2[0];
11730 decal->color4f[2][1] = c2[1];
11731 decal->color4f[2][2] = c2[2];
11732 decal->color4f[2][3] = 1;
11733 decal->vertex3f[0][0] = v0[0];
11734 decal->vertex3f[0][1] = v0[1];
11735 decal->vertex3f[0][2] = v0[2];
11736 decal->vertex3f[1][0] = v1[0];
11737 decal->vertex3f[1][1] = v1[1];
11738 decal->vertex3f[1][2] = v1[2];
11739 decal->vertex3f[2][0] = v2[0];
11740 decal->vertex3f[2][1] = v2[1];
11741 decal->vertex3f[2][2] = v2[2];
11742 decal->texcoord2f[0][0] = t0[0];
11743 decal->texcoord2f[0][1] = t0[1];
11744 decal->texcoord2f[1][0] = t1[0];
11745 decal->texcoord2f[1][1] = t1[1];
11746 decal->texcoord2f[2][0] = t2[0];
11747 decal->texcoord2f[2][1] = t2[1];
11748 TriangleNormal(v0, v1, v2, decal->plane);
11749 VectorNormalize(decal->plane);
11750 decal->plane[3] = DotProduct(v0, decal->plane);
11753 extern cvar_t cl_decals_bias;
11754 extern cvar_t cl_decals_models;
11755 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11756 // baseparms, parms, temps
11757 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)
11762 const float *vertex3f;
11763 const float *normal3f;
11765 float points[2][9][3];
11772 e = rsurface.modelelement3i + 3*triangleindex;
11774 vertex3f = rsurface.modelvertex3f;
11775 normal3f = rsurface.modelnormal3f;
11779 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11781 index = 3*e[cornerindex];
11782 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11787 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11789 index = 3*e[cornerindex];
11790 VectorCopy(vertex3f + index, v[cornerindex]);
11795 //TriangleNormal(v[0], v[1], v[2], normal);
11796 //if (DotProduct(normal, localnormal) < 0.0f)
11798 // clip by each of the box planes formed from the projection matrix
11799 // if anything survives, we emit the decal
11800 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]);
11803 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]);
11806 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]);
11809 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]);
11812 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]);
11815 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]);
11818 // some part of the triangle survived, so we have to accept it...
11821 // dynamic always uses the original triangle
11823 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11825 index = 3*e[cornerindex];
11826 VectorCopy(vertex3f + index, v[cornerindex]);
11829 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11831 // convert vertex positions to texcoords
11832 Matrix4x4_Transform(projection, v[cornerindex], temp);
11833 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11834 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11835 // calculate distance fade from the projection origin
11836 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11837 f = bound(0.0f, f, 1.0f);
11838 c[cornerindex][0] = r * f;
11839 c[cornerindex][1] = g * f;
11840 c[cornerindex][2] = b * f;
11841 c[cornerindex][3] = 1.0f;
11842 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11845 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);
11847 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11848 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);
11850 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)
11852 matrix4x4_t projection;
11853 decalsystem_t *decalsystem;
11856 const msurface_t *surface;
11857 const msurface_t *surfaces;
11858 const int *surfacelist;
11859 const texture_t *texture;
11861 int numsurfacelist;
11862 int surfacelistindex;
11865 float localorigin[3];
11866 float localnormal[3];
11867 float localmins[3];
11868 float localmaxs[3];
11871 float planes[6][4];
11874 int bih_triangles_count;
11875 int bih_triangles[256];
11876 int bih_surfaces[256];
11878 decalsystem = &ent->decalsystem;
11879 model = ent->model;
11880 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11882 R_DecalSystem_Reset(&ent->decalsystem);
11886 if (!model->brush.data_leafs && !cl_decals_models.integer)
11888 if (decalsystem->model)
11889 R_DecalSystem_Reset(decalsystem);
11893 if (decalsystem->model != model)
11894 R_DecalSystem_Reset(decalsystem);
11895 decalsystem->model = model;
11897 RSurf_ActiveModelEntity(ent, true, false, false);
11899 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11900 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11901 VectorNormalize(localnormal);
11902 localsize = worldsize*rsurface.inversematrixscale;
11903 localmins[0] = localorigin[0] - localsize;
11904 localmins[1] = localorigin[1] - localsize;
11905 localmins[2] = localorigin[2] - localsize;
11906 localmaxs[0] = localorigin[0] + localsize;
11907 localmaxs[1] = localorigin[1] + localsize;
11908 localmaxs[2] = localorigin[2] + localsize;
11910 //VectorCopy(localnormal, planes[4]);
11911 //VectorVectors(planes[4], planes[2], planes[0]);
11912 AnglesFromVectors(angles, localnormal, NULL, false);
11913 AngleVectors(angles, planes[0], planes[2], planes[4]);
11914 VectorNegate(planes[0], planes[1]);
11915 VectorNegate(planes[2], planes[3]);
11916 VectorNegate(planes[4], planes[5]);
11917 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11918 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11919 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11920 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11921 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11922 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11927 matrix4x4_t forwardprojection;
11928 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11929 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11934 float projectionvector[4][3];
11935 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11936 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11937 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11938 projectionvector[0][0] = planes[0][0] * ilocalsize;
11939 projectionvector[0][1] = planes[1][0] * ilocalsize;
11940 projectionvector[0][2] = planes[2][0] * ilocalsize;
11941 projectionvector[1][0] = planes[0][1] * ilocalsize;
11942 projectionvector[1][1] = planes[1][1] * ilocalsize;
11943 projectionvector[1][2] = planes[2][1] * ilocalsize;
11944 projectionvector[2][0] = planes[0][2] * ilocalsize;
11945 projectionvector[2][1] = planes[1][2] * ilocalsize;
11946 projectionvector[2][2] = planes[2][2] * ilocalsize;
11947 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11948 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11949 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11950 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11954 dynamic = model->surfmesh.isanimated;
11955 numsurfacelist = model->nummodelsurfaces;
11956 surfacelist = model->sortedmodelsurfaces;
11957 surfaces = model->data_surfaces;
11960 bih_triangles_count = -1;
11963 if(model->render_bih.numleafs)
11964 bih = &model->render_bih;
11965 else if(model->collision_bih.numleafs)
11966 bih = &model->collision_bih;
11969 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11970 if(bih_triangles_count == 0)
11972 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11974 if(bih_triangles_count > 0)
11976 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11978 surfaceindex = bih_surfaces[triangleindex];
11979 surface = surfaces + surfaceindex;
11980 texture = surface->texture;
11981 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11983 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11985 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11990 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11992 surfaceindex = surfacelist[surfacelistindex];
11993 surface = surfaces + surfaceindex;
11994 // check cull box first because it rejects more than any other check
11995 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11997 // skip transparent surfaces
11998 texture = surface->texture;
11999 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12001 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12003 numtriangles = surface->num_triangles;
12004 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12005 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12010 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12011 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)
12013 int renderentityindex;
12014 float worldmins[3];
12015 float worldmaxs[3];
12016 entity_render_t *ent;
12018 if (!cl_decals_newsystem.integer)
12021 worldmins[0] = worldorigin[0] - worldsize;
12022 worldmins[1] = worldorigin[1] - worldsize;
12023 worldmins[2] = worldorigin[2] - worldsize;
12024 worldmaxs[0] = worldorigin[0] + worldsize;
12025 worldmaxs[1] = worldorigin[1] + worldsize;
12026 worldmaxs[2] = worldorigin[2] + worldsize;
12028 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12030 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12032 ent = r_refdef.scene.entities[renderentityindex];
12033 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12036 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12040 typedef struct r_decalsystem_splatqueue_s
12042 vec3_t worldorigin;
12043 vec3_t worldnormal;
12047 unsigned int decalsequence;
12049 r_decalsystem_splatqueue_t;
12051 int r_decalsystem_numqueued = 0;
12052 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12054 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)
12056 r_decalsystem_splatqueue_t *queue;
12058 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12061 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12062 VectorCopy(worldorigin, queue->worldorigin);
12063 VectorCopy(worldnormal, queue->worldnormal);
12064 Vector4Set(queue->color, r, g, b, a);
12065 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12066 queue->worldsize = worldsize;
12067 queue->decalsequence = cl.decalsequence++;
12070 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12073 r_decalsystem_splatqueue_t *queue;
12075 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12076 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);
12077 r_decalsystem_numqueued = 0;
12080 extern cvar_t cl_decals_max;
12081 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12084 decalsystem_t *decalsystem = &ent->decalsystem;
12086 unsigned int killsequence;
12091 if (!decalsystem->numdecals)
12094 if (r_showsurfaces.integer)
12097 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12099 R_DecalSystem_Reset(decalsystem);
12103 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12104 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12106 if (decalsystem->lastupdatetime)
12107 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12110 decalsystem->lastupdatetime = r_refdef.scene.time;
12111 numdecals = decalsystem->numdecals;
12113 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12115 if (decal->color4f[0][3])
12117 decal->lived += frametime;
12118 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12120 memset(decal, 0, sizeof(*decal));
12121 if (decalsystem->freedecal > i)
12122 decalsystem->freedecal = i;
12126 decal = decalsystem->decals;
12127 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12130 // collapse the array by shuffling the tail decals into the gaps
12133 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12134 decalsystem->freedecal++;
12135 if (decalsystem->freedecal == numdecals)
12137 decal[decalsystem->freedecal] = decal[--numdecals];
12140 decalsystem->numdecals = numdecals;
12142 if (numdecals <= 0)
12144 // if there are no decals left, reset decalsystem
12145 R_DecalSystem_Reset(decalsystem);
12149 extern skinframe_t *decalskinframe;
12150 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12153 decalsystem_t *decalsystem = &ent->decalsystem;
12162 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12165 numdecals = decalsystem->numdecals;
12169 if (r_showsurfaces.integer)
12172 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12174 R_DecalSystem_Reset(decalsystem);
12178 // if the model is static it doesn't matter what value we give for
12179 // wantnormals and wanttangents, so this logic uses only rules applicable
12180 // to a model, knowing that they are meaningless otherwise
12181 if (ent == r_refdef.scene.worldentity)
12182 RSurf_ActiveWorldEntity();
12184 RSurf_ActiveModelEntity(ent, false, false, false);
12186 decalsystem->lastupdatetime = r_refdef.scene.time;
12188 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12190 // update vertex positions for animated models
12191 v3f = decalsystem->vertex3f;
12192 c4f = decalsystem->color4f;
12193 t2f = decalsystem->texcoord2f;
12194 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12196 if (!decal->color4f[0][3])
12199 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12203 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12206 // update color values for fading decals
12207 if (decal->lived >= cl_decals_time.value)
12208 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12212 c4f[ 0] = decal->color4f[0][0] * alpha;
12213 c4f[ 1] = decal->color4f[0][1] * alpha;
12214 c4f[ 2] = decal->color4f[0][2] * alpha;
12216 c4f[ 4] = decal->color4f[1][0] * alpha;
12217 c4f[ 5] = decal->color4f[1][1] * alpha;
12218 c4f[ 6] = decal->color4f[1][2] * alpha;
12220 c4f[ 8] = decal->color4f[2][0] * alpha;
12221 c4f[ 9] = decal->color4f[2][1] * alpha;
12222 c4f[10] = decal->color4f[2][2] * alpha;
12225 t2f[0] = decal->texcoord2f[0][0];
12226 t2f[1] = decal->texcoord2f[0][1];
12227 t2f[2] = decal->texcoord2f[1][0];
12228 t2f[3] = decal->texcoord2f[1][1];
12229 t2f[4] = decal->texcoord2f[2][0];
12230 t2f[5] = decal->texcoord2f[2][1];
12232 // update vertex positions for animated models
12233 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12235 e = rsurface.modelelement3i + 3*decal->triangleindex;
12236 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12237 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12238 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12242 VectorCopy(decal->vertex3f[0], v3f);
12243 VectorCopy(decal->vertex3f[1], v3f + 3);
12244 VectorCopy(decal->vertex3f[2], v3f + 6);
12247 if (r_refdef.fogenabled)
12249 alpha = RSurf_FogVertex(v3f);
12250 VectorScale(c4f, alpha, c4f);
12251 alpha = RSurf_FogVertex(v3f + 3);
12252 VectorScale(c4f + 4, alpha, c4f + 4);
12253 alpha = RSurf_FogVertex(v3f + 6);
12254 VectorScale(c4f + 8, alpha, c4f + 8);
12265 r_refdef.stats[r_stat_drawndecals] += numtris;
12267 // now render the decals all at once
12268 // (this assumes they all use one particle font texture!)
12269 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);
12270 // R_Mesh_ResetTextureState();
12271 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12272 GL_DepthMask(false);
12273 GL_DepthRange(0, 1);
12274 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12275 GL_DepthTest(true);
12276 GL_CullFace(GL_NONE);
12277 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12278 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12279 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12283 static void R_DrawModelDecals(void)
12287 // fade faster when there are too many decals
12288 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12289 for (i = 0;i < r_refdef.scene.numentities;i++)
12290 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12292 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12293 for (i = 0;i < r_refdef.scene.numentities;i++)
12294 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12295 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12297 R_DecalSystem_ApplySplatEntitiesQueue();
12299 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12300 for (i = 0;i < r_refdef.scene.numentities;i++)
12301 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12303 r_refdef.stats[r_stat_totaldecals] += numdecals;
12305 if (r_showsurfaces.integer)
12308 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12310 for (i = 0;i < r_refdef.scene.numentities;i++)
12312 if (!r_refdef.viewcache.entityvisible[i])
12314 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12315 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12319 extern cvar_t mod_collision_bih;
12320 static void R_DrawDebugModel(void)
12322 entity_render_t *ent = rsurface.entity;
12323 int i, j, flagsmask;
12324 const msurface_t *surface;
12325 dp_model_t *model = ent->model;
12327 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12330 if (r_showoverdraw.value > 0)
12332 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12333 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12334 R_SetupShader_Generic_NoTexture(false, false);
12335 GL_DepthTest(false);
12336 GL_DepthMask(false);
12337 GL_DepthRange(0, 1);
12338 GL_BlendFunc(GL_ONE, GL_ONE);
12339 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12341 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12343 rsurface.texture = R_GetCurrentTexture(surface->texture);
12344 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12346 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12347 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12348 if (!rsurface.texture->currentlayers->depthmask)
12349 GL_Color(c, 0, 0, 1.0f);
12350 else if (ent == r_refdef.scene.worldentity)
12351 GL_Color(c, c, c, 1.0f);
12353 GL_Color(0, c, 0, 1.0f);
12354 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12358 rsurface.texture = NULL;
12361 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12363 // R_Mesh_ResetTextureState();
12364 R_SetupShader_Generic_NoTexture(false, false);
12365 GL_DepthRange(0, 1);
12366 GL_DepthTest(!r_showdisabledepthtest.integer);
12367 GL_DepthMask(false);
12368 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12370 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12374 qboolean cullbox = false;
12375 const q3mbrush_t *brush;
12376 const bih_t *bih = &model->collision_bih;
12377 const bih_leaf_t *bihleaf;
12378 float vertex3f[3][3];
12379 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12380 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12382 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12384 switch (bihleaf->type)
12387 brush = model->brush.data_brushes + bihleaf->itemindex;
12388 if (brush->colbrushf && brush->colbrushf->numtriangles)
12390 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);
12391 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12392 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12395 case BIH_COLLISIONTRIANGLE:
12396 triangleindex = bihleaf->itemindex;
12397 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12398 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12399 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12400 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);
12401 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12402 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12404 case BIH_RENDERTRIANGLE:
12405 triangleindex = bihleaf->itemindex;
12406 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12407 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12408 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12409 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);
12410 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12411 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12417 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12420 if (r_showtris.integer && qglPolygonMode)
12422 if (r_showdisabledepthtest.integer)
12424 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12425 GL_DepthMask(false);
12429 GL_BlendFunc(GL_ONE, GL_ZERO);
12430 GL_DepthMask(true);
12432 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12433 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12435 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12437 rsurface.texture = R_GetCurrentTexture(surface->texture);
12438 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12440 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12441 if (!rsurface.texture->currentlayers->depthmask)
12442 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12443 else if (ent == r_refdef.scene.worldentity)
12444 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12446 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12447 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12451 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12452 rsurface.texture = NULL;
12455 if (r_shownormals.value != 0 && qglBegin)
12459 if (r_showdisabledepthtest.integer)
12461 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12462 GL_DepthMask(false);
12466 GL_BlendFunc(GL_ONE, GL_ZERO);
12467 GL_DepthMask(true);
12469 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12471 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12473 rsurface.texture = R_GetCurrentTexture(surface->texture);
12474 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12476 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12477 qglBegin(GL_LINES);
12478 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12480 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12482 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12483 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12484 qglVertex3f(v[0], v[1], v[2]);
12485 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12486 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12487 qglVertex3f(v[0], v[1], v[2]);
12490 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12492 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12494 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12495 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12496 qglVertex3f(v[0], v[1], v[2]);
12497 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12498 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12499 qglVertex3f(v[0], v[1], v[2]);
12502 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12504 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12506 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12507 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12508 qglVertex3f(v[0], v[1], v[2]);
12509 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12510 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12511 qglVertex3f(v[0], v[1], v[2]);
12514 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12516 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12518 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12519 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12520 qglVertex3f(v[0], v[1], v[2]);
12521 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12522 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12523 qglVertex3f(v[0], v[1], v[2]);
12530 rsurface.texture = NULL;
12535 int r_maxsurfacelist = 0;
12536 const msurface_t **r_surfacelist = NULL;
12537 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12539 int i, j, endj, flagsmask;
12540 dp_model_t *model = r_refdef.scene.worldmodel;
12541 msurface_t *surfaces;
12542 unsigned char *update;
12543 int numsurfacelist = 0;
12547 if (r_maxsurfacelist < model->num_surfaces)
12549 r_maxsurfacelist = model->num_surfaces;
12551 Mem_Free((msurface_t**)r_surfacelist);
12552 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12555 RSurf_ActiveWorldEntity();
12557 surfaces = model->data_surfaces;
12558 update = model->brushq1.lightmapupdateflags;
12560 // update light styles on this submodel
12561 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12563 model_brush_lightstyleinfo_t *style;
12564 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12566 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12568 int *list = style->surfacelist;
12569 style->value = r_refdef.scene.lightstylevalue[style->style];
12570 for (j = 0;j < style->numsurfaces;j++)
12571 update[list[j]] = true;
12576 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12580 R_DrawDebugModel();
12581 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12585 rsurface.lightmaptexture = NULL;
12586 rsurface.deluxemaptexture = NULL;
12587 rsurface.uselightmaptexture = false;
12588 rsurface.texture = NULL;
12589 rsurface.rtlight = NULL;
12590 numsurfacelist = 0;
12591 // add visible surfaces to draw list
12592 for (i = 0;i < model->nummodelsurfaces;i++)
12594 j = model->sortedmodelsurfaces[i];
12595 if (r_refdef.viewcache.world_surfacevisible[j])
12596 r_surfacelist[numsurfacelist++] = surfaces + j;
12598 // update lightmaps if needed
12599 if (model->brushq1.firstrender)
12601 model->brushq1.firstrender = false;
12602 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12604 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12608 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12609 if (r_refdef.viewcache.world_surfacevisible[j])
12611 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12613 // don't do anything if there were no surfaces
12614 if (!numsurfacelist)
12616 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12619 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12621 // add to stats if desired
12622 if (r_speeds.integer && !skysurfaces && !depthonly)
12624 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12625 for (j = 0;j < numsurfacelist;j++)
12626 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12629 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12632 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12634 int i, j, endj, flagsmask;
12635 dp_model_t *model = ent->model;
12636 msurface_t *surfaces;
12637 unsigned char *update;
12638 int numsurfacelist = 0;
12642 if (r_maxsurfacelist < model->num_surfaces)
12644 r_maxsurfacelist = model->num_surfaces;
12646 Mem_Free((msurface_t **)r_surfacelist);
12647 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12650 // if the model is static it doesn't matter what value we give for
12651 // wantnormals and wanttangents, so this logic uses only rules applicable
12652 // to a model, knowing that they are meaningless otherwise
12653 if (ent == r_refdef.scene.worldentity)
12654 RSurf_ActiveWorldEntity();
12655 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12656 RSurf_ActiveModelEntity(ent, false, false, false);
12658 RSurf_ActiveModelEntity(ent, true, true, true);
12659 else if (depthonly)
12661 switch (vid.renderpath)
12663 case RENDERPATH_GL20:
12664 case RENDERPATH_D3D9:
12665 case RENDERPATH_D3D10:
12666 case RENDERPATH_D3D11:
12667 case RENDERPATH_SOFT:
12668 case RENDERPATH_GLES2:
12669 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12671 case RENDERPATH_GL11:
12672 case RENDERPATH_GL13:
12673 case RENDERPATH_GLES1:
12674 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12680 switch (vid.renderpath)
12682 case RENDERPATH_GL20:
12683 case RENDERPATH_D3D9:
12684 case RENDERPATH_D3D10:
12685 case RENDERPATH_D3D11:
12686 case RENDERPATH_SOFT:
12687 case RENDERPATH_GLES2:
12688 RSurf_ActiveModelEntity(ent, true, true, false);
12690 case RENDERPATH_GL11:
12691 case RENDERPATH_GL13:
12692 case RENDERPATH_GLES1:
12693 RSurf_ActiveModelEntity(ent, true, false, false);
12698 surfaces = model->data_surfaces;
12699 update = model->brushq1.lightmapupdateflags;
12701 // update light styles
12702 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12704 model_brush_lightstyleinfo_t *style;
12705 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12707 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12709 int *list = style->surfacelist;
12710 style->value = r_refdef.scene.lightstylevalue[style->style];
12711 for (j = 0;j < style->numsurfaces;j++)
12712 update[list[j]] = true;
12717 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12721 R_DrawDebugModel();
12722 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12726 rsurface.lightmaptexture = NULL;
12727 rsurface.deluxemaptexture = NULL;
12728 rsurface.uselightmaptexture = false;
12729 rsurface.texture = NULL;
12730 rsurface.rtlight = NULL;
12731 numsurfacelist = 0;
12732 // add visible surfaces to draw list
12733 for (i = 0;i < model->nummodelsurfaces;i++)
12734 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12735 // don't do anything if there were no surfaces
12736 if (!numsurfacelist)
12738 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12741 // update lightmaps if needed
12745 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12750 R_BuildLightMap(ent, surfaces + j);
12755 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12757 // add to stats if desired
12758 if (r_speeds.integer && !skysurfaces && !depthonly)
12760 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12761 for (j = 0;j < numsurfacelist;j++)
12762 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12765 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12768 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12770 static texture_t texture;
12771 static msurface_t surface;
12772 const msurface_t *surfacelist = &surface;
12774 // fake enough texture and surface state to render this geometry
12776 texture.update_lastrenderframe = -1; // regenerate this texture
12777 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12778 texture.basealpha = 1.0f;
12779 texture.currentskinframe = skinframe;
12780 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12781 texture.offsetmapping = OFFSETMAPPING_OFF;
12782 texture.offsetscale = 1;
12783 texture.specularscalemod = 1;
12784 texture.specularpowermod = 1;
12785 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12786 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12787 // JUST GREP FOR "specularscalemod = 1".
12789 surface.texture = &texture;
12790 surface.num_triangles = numtriangles;
12791 surface.num_firsttriangle = firsttriangle;
12792 surface.num_vertices = numvertices;
12793 surface.num_firstvertex = firstvertex;
12796 rsurface.texture = R_GetCurrentTexture(surface.texture);
12797 rsurface.lightmaptexture = NULL;
12798 rsurface.deluxemaptexture = NULL;
12799 rsurface.uselightmaptexture = false;
12800 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12803 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)
12805 static msurface_t surface;
12806 const msurface_t *surfacelist = &surface;
12808 // fake enough texture and surface state to render this geometry
12809 surface.texture = texture;
12810 surface.num_triangles = numtriangles;
12811 surface.num_firsttriangle = firsttriangle;
12812 surface.num_vertices = numvertices;
12813 surface.num_firstvertex = firstvertex;
12816 rsurface.texture = R_GetCurrentTexture(surface.texture);
12817 rsurface.lightmaptexture = NULL;
12818 rsurface.deluxemaptexture = NULL;
12819 rsurface.uselightmaptexture = false;
12820 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);