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"
31 #include "cl_collision.h"
35 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
39 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
43 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
49 mempool_t *r_main_mempool;
50 rtexturepool_t *r_main_texturepool;
52 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
54 static qboolean r_loadnormalmap;
55 static qboolean r_loadgloss;
57 static qboolean r_loaddds;
58 static qboolean r_savedds;
59 static qboolean r_gpuskeletal;
66 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!"};
67 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!"};
68 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
69 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
70 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)"};
71 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
77 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"};
79 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
80 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"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
82 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)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
85 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"};
86 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
87 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
88 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
89 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
90 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
91 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
92 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"};
93 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"};
94 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"};
95 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
96 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
97 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%, 10 = 100%)" };
98 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)"};
99 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
100 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
101 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"};
102 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"};
103 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
104 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"};
105 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"};
106 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"};
107 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
108 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
109 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
110 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
111 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
112 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
113 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
114 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
115 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)"};
116 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)"};
117 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
118 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
119 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
120 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
121 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
122 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
124 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
126 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
128 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
129 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
130 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
131 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."};
132 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
133 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
134 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
135 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."};
136 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
137 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
138 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
139 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."};
140 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
141 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"};
142 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"};
143 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
144 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
145 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
146 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
147 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
148 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"};
149 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
150 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
151 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
152 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
153 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
155 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
156 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
157 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
158 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
159 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
160 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
161 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
162 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
164 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)"};
165 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"};
167 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
168 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
169 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
171 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"};
172 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"};
173 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"};
174 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
175 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
176 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"};
177 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)"};
178 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)"};
179 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
181 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
182 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)"};
183 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
184 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)"};
185 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
186 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)"};
187 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)"};
188 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
189 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"};
190 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."};
191 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
192 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)"};
193 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)"};
194 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)"};
195 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)"};
196 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)"};
197 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)"};
198 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)"};
199 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)"};
201 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)"};
202 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)"};
203 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
204 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"};
205 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
206 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
207 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
208 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"};
209 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"};
210 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)"};
212 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
213 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
214 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
215 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
217 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
218 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
220 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
221 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
222 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
223 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
224 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
225 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
227 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
228 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
229 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
230 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
231 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
232 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
233 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
234 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
235 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
236 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
238 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"};
240 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"};
242 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
244 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
246 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)"};
247 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)"};
248 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
249 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
251 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
252 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"};
254 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."};
256 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)"};
257 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
259 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
260 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
261 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
262 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
265 extern cvar_t v_glslgamma;
266 extern cvar_t v_glslgamma_2d;
268 extern qboolean v_flipped_state;
270 r_framebufferstate_t r_fb;
272 /// shadow volume bsp struct with automatically growing nodes buffer
275 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
277 rtexture_t *r_texture_blanknormalmap;
278 rtexture_t *r_texture_white;
279 rtexture_t *r_texture_grey128;
280 rtexture_t *r_texture_black;
281 rtexture_t *r_texture_notexture;
282 rtexture_t *r_texture_whitecube;
283 rtexture_t *r_texture_normalizationcube;
284 rtexture_t *r_texture_fogattenuation;
285 rtexture_t *r_texture_fogheighttexture;
286 rtexture_t *r_texture_gammaramps;
287 unsigned int r_texture_gammaramps_serial;
288 //rtexture_t *r_texture_fogintensity;
289 rtexture_t *r_texture_reflectcube;
291 // TODO: hash lookups?
292 typedef struct cubemapinfo_s
299 int r_texture_numcubemaps;
300 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
302 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
303 unsigned int r_numqueries;
304 unsigned int r_maxqueries;
306 typedef struct r_qwskincache_s
308 char name[MAX_QPATH];
309 skinframe_t *skinframe;
313 static r_qwskincache_t *r_qwskincache;
314 static int r_qwskincache_size;
316 /// vertex coordinates for a quad that covers the screen exactly
317 extern const float r_screenvertex3f[12];
318 extern const float r_d3dscreenvertex3f[12];
319 const float r_screenvertex3f[12] =
326 const float r_d3dscreenvertex3f[12] =
334 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
337 for (i = 0;i < verts;i++)
348 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
351 for (i = 0;i < verts;i++)
361 // FIXME: move this to client?
364 if (gamemode == GAME_NEHAHRA)
366 Cvar_Set("gl_fogenable", "0");
367 Cvar_Set("gl_fogdensity", "0.2");
368 Cvar_Set("gl_fogred", "0.3");
369 Cvar_Set("gl_foggreen", "0.3");
370 Cvar_Set("gl_fogblue", "0.3");
372 r_refdef.fog_density = 0;
373 r_refdef.fog_red = 0;
374 r_refdef.fog_green = 0;
375 r_refdef.fog_blue = 0;
376 r_refdef.fog_alpha = 1;
377 r_refdef.fog_start = 0;
378 r_refdef.fog_end = 16384;
379 r_refdef.fog_height = 1<<30;
380 r_refdef.fog_fadedepth = 128;
381 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
384 static void R_BuildBlankTextures(void)
386 unsigned char data[4];
387 data[2] = 128; // normal X
388 data[1] = 128; // normal Y
389 data[0] = 255; // normal Z
390 data[3] = 255; // height
391 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
401 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
406 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
409 static void R_BuildNoTexture(void)
412 unsigned char pix[16][16][4];
413 // this makes a light grey/dark grey checkerboard texture
414 for (y = 0;y < 16;y++)
416 for (x = 0;x < 16;x++)
418 if ((y < 8) ^ (x < 8))
434 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
437 static void R_BuildWhiteCube(void)
439 unsigned char data[6*1*1*4];
440 memset(data, 255, sizeof(data));
441 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
444 static void R_BuildNormalizationCube(void)
448 vec_t s, t, intensity;
451 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
452 for (side = 0;side < 6;side++)
454 for (y = 0;y < NORMSIZE;y++)
456 for (x = 0;x < NORMSIZE;x++)
458 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
459 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
494 intensity = 127.0f / sqrt(DotProduct(v, v));
495 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
496 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
497 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
498 data[((side*64+y)*64+x)*4+3] = 255;
502 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
506 static void R_BuildFogTexture(void)
510 unsigned char data1[FOGWIDTH][4];
511 //unsigned char data2[FOGWIDTH][4];
514 r_refdef.fogmasktable_start = r_refdef.fog_start;
515 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
516 r_refdef.fogmasktable_range = r_refdef.fogrange;
517 r_refdef.fogmasktable_density = r_refdef.fog_density;
519 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
520 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
522 d = (x * r - r_refdef.fogmasktable_start);
523 if(developer_extra.integer)
524 Con_DPrintf("%f ", d);
526 if (r_fog_exp2.integer)
527 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
529 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
530 if(developer_extra.integer)
531 Con_DPrintf(" : %f ", alpha);
532 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
533 if(developer_extra.integer)
534 Con_DPrintf(" = %f\n", alpha);
535 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
538 for (x = 0;x < FOGWIDTH;x++)
540 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
545 //data2[x][0] = 255 - b;
546 //data2[x][1] = 255 - b;
547 //data2[x][2] = 255 - b;
550 if (r_texture_fogattenuation)
552 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
553 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
557 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
558 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
562 static void R_BuildFogHeightTexture(void)
564 unsigned char *inpixels;
572 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
573 if (r_refdef.fogheighttexturename[0])
574 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
577 r_refdef.fog_height_tablesize = 0;
578 if (r_texture_fogheighttexture)
579 R_FreeTexture(r_texture_fogheighttexture);
580 r_texture_fogheighttexture = NULL;
581 if (r_refdef.fog_height_table2d)
582 Mem_Free(r_refdef.fog_height_table2d);
583 r_refdef.fog_height_table2d = NULL;
584 if (r_refdef.fog_height_table1d)
585 Mem_Free(r_refdef.fog_height_table1d);
586 r_refdef.fog_height_table1d = NULL;
590 r_refdef.fog_height_tablesize = size;
591 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
592 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
593 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
595 // LordHavoc: now the magic - what is that table2d for? it is a cooked
596 // average fog color table accounting for every fog layer between a point
597 // and the camera. (Note: attenuation is handled separately!)
598 for (y = 0;y < size;y++)
600 for (x = 0;x < size;x++)
606 for (j = x;j <= y;j++)
608 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
614 for (j = x;j >= y;j--)
616 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
621 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
622 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
623 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
624 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
627 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
630 //=======================================================================================================================================================
632 static const char *builtinshaderstrings[] =
634 #include "shader_glsl.h"
638 const char *builtinhlslshaderstrings[] =
640 #include "shader_hlsl.h"
644 //=======================================================================================================================================================
646 typedef struct shaderpermutationinfo_s
651 shaderpermutationinfo_t;
653 typedef struct shadermodeinfo_s
655 const char *sourcebasename;
656 const char *extension;
657 const char **builtinshaderstrings;
666 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
667 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
669 {"#define USEDIFFUSE\n", " diffuse"},
670 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
671 {"#define USEVIEWTINT\n", " viewtint"},
672 {"#define USECOLORMAPPING\n", " colormapping"},
673 {"#define USESATURATION\n", " saturation"},
674 {"#define USEFOGINSIDE\n", " foginside"},
675 {"#define USEFOGOUTSIDE\n", " fogoutside"},
676 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
677 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
678 {"#define USEGAMMARAMPS\n", " gammaramps"},
679 {"#define USECUBEFILTER\n", " cubefilter"},
680 {"#define USEGLOW\n", " glow"},
681 {"#define USEBLOOM\n", " bloom"},
682 {"#define USESPECULAR\n", " specular"},
683 {"#define USEPOSTPROCESSING\n", " postprocessing"},
684 {"#define USEREFLECTION\n", " reflection"},
685 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
686 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
687 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
688 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
689 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
690 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
691 {"#define USEALPHAKILL\n", " alphakill"},
692 {"#define USEREFLECTCUBE\n", " reflectcube"},
693 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
694 {"#define USEBOUNCEGRID\n", " bouncegrid"},
695 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
696 {"#define USETRIPPY\n", " trippy"},
697 {"#define USEDEPTHRGB\n", " depthrgb"},
698 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
699 {"#define USESKELETAL\n", " skeletal"},
700 {"#define USEOCCLUDE\n", " occlude"}
703 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
704 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
706 // SHADERLANGUAGE_GLSL
708 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
709 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
710 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
712 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
714 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
715 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
721 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
722 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
723 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
726 // SHADERLANGUAGE_HLSL
728 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
729 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
730 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
731 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
732 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
733 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
734 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
735 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
736 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
737 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
738 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
739 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
740 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
741 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
742 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
743 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
744 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
748 struct r_glsl_permutation_s;
749 typedef struct r_glsl_permutation_s
752 struct r_glsl_permutation_s *hashnext;
754 dpuint64 permutation;
756 /// indicates if we have tried compiling this permutation already
758 /// 0 if compilation failed
760 // texture units assigned to each detected uniform
761 int tex_Texture_First;
762 int tex_Texture_Second;
763 int tex_Texture_GammaRamps;
764 int tex_Texture_Normal;
765 int tex_Texture_Color;
766 int tex_Texture_Gloss;
767 int tex_Texture_Glow;
768 int tex_Texture_SecondaryNormal;
769 int tex_Texture_SecondaryColor;
770 int tex_Texture_SecondaryGloss;
771 int tex_Texture_SecondaryGlow;
772 int tex_Texture_Pants;
773 int tex_Texture_Shirt;
774 int tex_Texture_FogHeightTexture;
775 int tex_Texture_FogMask;
776 int tex_Texture_Lightmap;
777 int tex_Texture_Deluxemap;
778 int tex_Texture_Attenuation;
779 int tex_Texture_Cube;
780 int tex_Texture_Refraction;
781 int tex_Texture_Reflection;
782 int tex_Texture_ShadowMap2D;
783 int tex_Texture_CubeProjection;
784 int tex_Texture_ScreenNormalMap;
785 int tex_Texture_ScreenDiffuse;
786 int tex_Texture_ScreenSpecular;
787 int tex_Texture_ReflectMask;
788 int tex_Texture_ReflectCube;
789 int tex_Texture_BounceGrid;
790 /// locations of detected uniforms in program object, or -1 if not found
791 int loc_Texture_First;
792 int loc_Texture_Second;
793 int loc_Texture_GammaRamps;
794 int loc_Texture_Normal;
795 int loc_Texture_Color;
796 int loc_Texture_Gloss;
797 int loc_Texture_Glow;
798 int loc_Texture_SecondaryNormal;
799 int loc_Texture_SecondaryColor;
800 int loc_Texture_SecondaryGloss;
801 int loc_Texture_SecondaryGlow;
802 int loc_Texture_Pants;
803 int loc_Texture_Shirt;
804 int loc_Texture_FogHeightTexture;
805 int loc_Texture_FogMask;
806 int loc_Texture_Lightmap;
807 int loc_Texture_Deluxemap;
808 int loc_Texture_Attenuation;
809 int loc_Texture_Cube;
810 int loc_Texture_Refraction;
811 int loc_Texture_Reflection;
812 int loc_Texture_ShadowMap2D;
813 int loc_Texture_CubeProjection;
814 int loc_Texture_ScreenNormalMap;
815 int loc_Texture_ScreenDiffuse;
816 int loc_Texture_ScreenSpecular;
817 int loc_Texture_ReflectMask;
818 int loc_Texture_ReflectCube;
819 int loc_Texture_BounceGrid;
821 int loc_BloomBlur_Parameters;
823 int loc_Color_Ambient;
824 int loc_Color_Diffuse;
825 int loc_Color_Specular;
829 int loc_DeferredColor_Ambient;
830 int loc_DeferredColor_Diffuse;
831 int loc_DeferredColor_Specular;
832 int loc_DeferredMod_Diffuse;
833 int loc_DeferredMod_Specular;
834 int loc_DistortScaleRefractReflect;
837 int loc_FogHeightFade;
839 int loc_FogPlaneViewDist;
840 int loc_FogRangeRecip;
843 int loc_LightPosition;
844 int loc_OffsetMapping_ScaleSteps;
845 int loc_OffsetMapping_LodDistance;
846 int loc_OffsetMapping_Bias;
848 int loc_ReflectColor;
849 int loc_ReflectFactor;
850 int loc_ReflectOffset;
851 int loc_RefractColor;
853 int loc_ScreenCenterRefractReflect;
854 int loc_ScreenScaleRefractReflect;
855 int loc_ScreenToDepth;
856 int loc_ShadowMap_Parameters;
857 int loc_ShadowMap_TextureScale;
858 int loc_SpecularPower;
859 int loc_Skeletal_Transform12;
864 int loc_ViewTintColor;
866 int loc_ModelToLight;
868 int loc_BackgroundTexMatrix;
869 int loc_ModelViewProjectionMatrix;
870 int loc_ModelViewMatrix;
871 int loc_PixelToScreenTexCoord;
872 int loc_ModelToReflectCube;
873 int loc_ShadowMapMatrix;
874 int loc_BloomColorSubtract;
875 int loc_NormalmapScrollBlend;
876 int loc_BounceGridMatrix;
877 int loc_BounceGridIntensity;
878 /// uniform block bindings
879 int ubibind_Skeletal_Transform12_UniformBlock;
880 /// uniform block indices
881 int ubiloc_Skeletal_Transform12_UniformBlock;
883 r_glsl_permutation_t;
885 #define SHADERPERMUTATION_HASHSIZE 256
888 // non-degradable "lightweight" shader parameters to keep the permutations simpler
889 // these can NOT degrade! only use for simple stuff
892 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
893 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
894 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
895 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
896 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
897 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
898 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
899 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
900 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
901 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
902 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
903 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
904 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
905 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
907 #define SHADERSTATICPARMS_COUNT 14
909 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
910 static int shaderstaticparms_count = 0;
912 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
913 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
915 extern qboolean r_shadow_shadowmapsampler;
916 extern int r_shadow_shadowmappcf;
917 qboolean R_CompileShader_CheckStaticParms(void)
919 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
920 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
921 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
924 if (r_glsl_saturation_redcompensate.integer)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
926 if (r_glsl_vertextextureblend_usebothalphas.integer)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
928 if (r_shadow_glossexact.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
930 if (r_glsl_postprocess.integer)
932 if (r_glsl_postprocess_uservec1_enable.integer)
933 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
934 if (r_glsl_postprocess_uservec2_enable.integer)
935 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
936 if (r_glsl_postprocess_uservec3_enable.integer)
937 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
938 if (r_glsl_postprocess_uservec4_enable.integer)
939 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
942 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
943 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
944 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
946 if (r_shadow_shadowmapsampler)
947 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
948 if (r_shadow_shadowmappcf > 1)
949 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
950 else if (r_shadow_shadowmappcf)
951 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
952 if (r_celshading.integer)
953 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
954 if (r_celoutlines.integer)
955 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
957 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
960 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
961 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
962 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
964 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
965 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
967 shaderstaticparms_count = 0;
970 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
971 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
972 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
973 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
974 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
975 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
976 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
977 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
978 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
979 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
980 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
981 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
982 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
983 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
986 /// information about each possible shader permutation
987 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
988 /// currently selected permutation
989 r_glsl_permutation_t *r_glsl_permutation;
990 /// storage for permutations linked in the hash table
991 memexpandablearray_t r_glsl_permutationarray;
993 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
995 //unsigned int hashdepth = 0;
996 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
997 r_glsl_permutation_t *p;
998 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1000 if (p->mode == mode && p->permutation == permutation)
1002 //if (hashdepth > 10)
1003 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1008 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1010 p->permutation = permutation;
1011 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1012 r_glsl_permutationhash[mode][hashindex] = p;
1013 //if (hashdepth > 10)
1014 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1018 static char *R_ShaderStrCat(const char **strings)
1021 const char **p = strings;
1024 for (p = strings;(t = *p);p++)
1027 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1029 for (p = strings;(t = *p);p++)
1039 static char *R_ShaderStrCat(const char **strings);
1040 static void R_InitShaderModeInfo(void)
1043 shadermodeinfo_t *modeinfo;
1044 // 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)
1045 for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1047 for (i = 0; i < SHADERMODE_COUNT; i++)
1049 char filename[MAX_QPATH];
1050 modeinfo = &shadermodeinfo[language][i];
1051 modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1052 modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1053 dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1054 modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1059 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1062 // if the mode has no filename we have to return the builtin string
1063 if (builtinonly || !modeinfo->filename)
1064 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1065 // note that FS_LoadFile appends a 0 byte to make it a valid string
1066 shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1069 if (printfromdisknotice)
1070 Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1071 return shaderstring;
1073 // fall back to builtinstring
1074 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1077 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1082 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1084 char permutationname[256];
1085 int vertstrings_count = 0;
1086 int geomstrings_count = 0;
1087 int fragstrings_count = 0;
1088 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1089 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1090 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1097 permutationname[0] = 0;
1098 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1100 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1102 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1103 if(vid.support.glshaderversion >= 140)
1105 vertstrings_list[vertstrings_count++] = "#version 140\n";
1106 geomstrings_list[geomstrings_count++] = "#version 140\n";
1107 fragstrings_list[fragstrings_count++] = "#version 140\n";
1108 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1109 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1110 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1112 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1113 else if(vid.support.glshaderversion >= 130)
1115 vertstrings_list[vertstrings_count++] = "#version 130\n";
1116 geomstrings_list[geomstrings_count++] = "#version 130\n";
1117 fragstrings_list[fragstrings_count++] = "#version 130\n";
1118 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1119 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1120 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1122 // if we can do #version 120, we should (this adds the invariant keyword)
1123 else if(vid.support.glshaderversion >= 120)
1125 vertstrings_list[vertstrings_count++] = "#version 120\n";
1126 geomstrings_list[geomstrings_count++] = "#version 120\n";
1127 fragstrings_list[fragstrings_count++] = "#version 120\n";
1128 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1129 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1130 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1132 // GLES also adds several things from GLSL120
1133 switch(vid.renderpath)
1135 case RENDERPATH_GLES2:
1136 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1137 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1138 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1144 // the first pretext is which type of shader to compile as
1145 // (later these will all be bound together as a program object)
1146 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1147 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1148 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1150 // the second pretext is the mode (for example a light source)
1151 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1152 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1153 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1154 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1156 // now add all the permutation pretexts
1157 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1159 if (permutation & (1ll<<i))
1161 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1162 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1163 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1164 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1168 // keep line numbers correct
1169 vertstrings_list[vertstrings_count++] = "\n";
1170 geomstrings_list[geomstrings_count++] = "\n";
1171 fragstrings_list[fragstrings_count++] = "\n";
1176 R_CompileShader_AddStaticParms(mode, permutation);
1177 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178 vertstrings_count += shaderstaticparms_count;
1179 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1180 geomstrings_count += shaderstaticparms_count;
1181 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1182 fragstrings_count += shaderstaticparms_count;
1184 // now append the shader text itself
1185 vertstrings_list[vertstrings_count++] = sourcestring;
1186 geomstrings_list[geomstrings_count++] = sourcestring;
1187 fragstrings_list[fragstrings_count++] = sourcestring;
1189 // compile the shader program
1190 if (vertstrings_count + geomstrings_count + fragstrings_count)
1191 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1195 qglUseProgram(p->program);CHECKGLERROR
1196 // look up all the uniform variable names we care about, so we don't
1197 // have to look them up every time we set them
1202 GLint activeuniformindex = 0;
1203 GLint numactiveuniforms = 0;
1204 char uniformname[128];
1205 GLsizei uniformnamelength = 0;
1206 GLint uniformsize = 0;
1207 GLenum uniformtype = 0;
1208 memset(uniformname, 0, sizeof(uniformname));
1209 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1210 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1211 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1213 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1214 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1219 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1220 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1221 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1222 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1223 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1224 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1225 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1226 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1227 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1228 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1229 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1230 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1231 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1232 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1233 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1234 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1235 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1236 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1237 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1238 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1239 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1240 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1241 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1242 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1243 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1244 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1245 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1246 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1247 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1248 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1249 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1250 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1251 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1252 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1253 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1254 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1255 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1256 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1257 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1258 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1259 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1260 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1261 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1262 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1263 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1264 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1265 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1266 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1267 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1268 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1269 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1270 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1271 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1272 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1273 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1274 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1275 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1276 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1277 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1278 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1279 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1280 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1281 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1282 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1283 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1284 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1285 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1286 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1287 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1288 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1289 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1290 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1291 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1292 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1293 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1294 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1295 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1296 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1297 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1298 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1299 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1300 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1301 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1302 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1303 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1304 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1305 // initialize the samplers to refer to the texture units we use
1306 p->tex_Texture_First = -1;
1307 p->tex_Texture_Second = -1;
1308 p->tex_Texture_GammaRamps = -1;
1309 p->tex_Texture_Normal = -1;
1310 p->tex_Texture_Color = -1;
1311 p->tex_Texture_Gloss = -1;
1312 p->tex_Texture_Glow = -1;
1313 p->tex_Texture_SecondaryNormal = -1;
1314 p->tex_Texture_SecondaryColor = -1;
1315 p->tex_Texture_SecondaryGloss = -1;
1316 p->tex_Texture_SecondaryGlow = -1;
1317 p->tex_Texture_Pants = -1;
1318 p->tex_Texture_Shirt = -1;
1319 p->tex_Texture_FogHeightTexture = -1;
1320 p->tex_Texture_FogMask = -1;
1321 p->tex_Texture_Lightmap = -1;
1322 p->tex_Texture_Deluxemap = -1;
1323 p->tex_Texture_Attenuation = -1;
1324 p->tex_Texture_Cube = -1;
1325 p->tex_Texture_Refraction = -1;
1326 p->tex_Texture_Reflection = -1;
1327 p->tex_Texture_ShadowMap2D = -1;
1328 p->tex_Texture_CubeProjection = -1;
1329 p->tex_Texture_ScreenNormalMap = -1;
1330 p->tex_Texture_ScreenDiffuse = -1;
1331 p->tex_Texture_ScreenSpecular = -1;
1332 p->tex_Texture_ReflectMask = -1;
1333 p->tex_Texture_ReflectCube = -1;
1334 p->tex_Texture_BounceGrid = -1;
1335 // bind the texture samplers in use
1337 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1338 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1339 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1340 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1341 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1342 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1343 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1344 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1345 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1346 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1347 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1348 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1349 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1350 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1351 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1352 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1353 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1354 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1355 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1356 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1357 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1358 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1359 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1360 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1361 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1362 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1363 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1364 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1365 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1366 // get the uniform block indices so we can bind them
1367 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1368 if (vid.support.arb_uniform_buffer_object)
1369 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1372 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1373 // clear the uniform block bindings
1374 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1375 // bind the uniform blocks in use
1377 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1378 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1380 // we're done compiling and setting up the shader, at least until it is used
1382 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1385 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1389 Mem_Free(sourcestring);
1392 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1394 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1395 if (r_glsl_permutation != perm)
1397 r_glsl_permutation = perm;
1398 if (!r_glsl_permutation->program)
1400 if (!r_glsl_permutation->compiled)
1402 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1403 R_GLSL_CompilePermutation(perm, mode, permutation);
1405 if (!r_glsl_permutation->program)
1407 // remove features until we find a valid permutation
1409 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1411 // reduce i more quickly whenever it would not remove any bits
1412 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1413 if (!(permutation & j))
1416 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1417 if (!r_glsl_permutation->compiled)
1418 R_GLSL_CompilePermutation(perm, mode, permutation);
1419 if (r_glsl_permutation->program)
1422 if (i >= SHADERPERMUTATION_COUNT)
1424 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1425 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1426 qglUseProgram(0);CHECKGLERROR
1427 return; // no bit left to clear, entire mode is broken
1432 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1434 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1435 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1436 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1444 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1445 extern D3DCAPS9 vid_d3d9caps;
1448 struct r_hlsl_permutation_s;
1449 typedef struct r_hlsl_permutation_s
1451 /// hash lookup data
1452 struct r_hlsl_permutation_s *hashnext;
1454 dpuint64 permutation;
1456 /// indicates if we have tried compiling this permutation already
1458 /// NULL if compilation failed
1459 IDirect3DVertexShader9 *vertexshader;
1460 IDirect3DPixelShader9 *pixelshader;
1462 r_hlsl_permutation_t;
1464 typedef enum D3DVSREGISTER_e
1466 D3DVSREGISTER_TexMatrix = 0, // float4x4
1467 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1468 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1469 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1470 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1471 D3DVSREGISTER_ModelToLight = 20, // float4x4
1472 D3DVSREGISTER_EyePosition = 24,
1473 D3DVSREGISTER_FogPlane = 25,
1474 D3DVSREGISTER_LightDir = 26,
1475 D3DVSREGISTER_LightPosition = 27,
1479 typedef enum D3DPSREGISTER_e
1481 D3DPSREGISTER_Alpha = 0,
1482 D3DPSREGISTER_BloomBlur_Parameters = 1,
1483 D3DPSREGISTER_ClientTime = 2,
1484 D3DPSREGISTER_Color_Ambient = 3,
1485 D3DPSREGISTER_Color_Diffuse = 4,
1486 D3DPSREGISTER_Color_Specular = 5,
1487 D3DPSREGISTER_Color_Glow = 6,
1488 D3DPSREGISTER_Color_Pants = 7,
1489 D3DPSREGISTER_Color_Shirt = 8,
1490 D3DPSREGISTER_DeferredColor_Ambient = 9,
1491 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1492 D3DPSREGISTER_DeferredColor_Specular = 11,
1493 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1494 D3DPSREGISTER_DeferredMod_Specular = 13,
1495 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1496 D3DPSREGISTER_EyePosition = 15, // unused
1497 D3DPSREGISTER_FogColor = 16,
1498 D3DPSREGISTER_FogHeightFade = 17,
1499 D3DPSREGISTER_FogPlane = 18,
1500 D3DPSREGISTER_FogPlaneViewDist = 19,
1501 D3DPSREGISTER_FogRangeRecip = 20,
1502 D3DPSREGISTER_LightColor = 21,
1503 D3DPSREGISTER_LightDir = 22, // unused
1504 D3DPSREGISTER_LightPosition = 23,
1505 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1506 D3DPSREGISTER_PixelSize = 25,
1507 D3DPSREGISTER_ReflectColor = 26,
1508 D3DPSREGISTER_ReflectFactor = 27,
1509 D3DPSREGISTER_ReflectOffset = 28,
1510 D3DPSREGISTER_RefractColor = 29,
1511 D3DPSREGISTER_Saturation = 30,
1512 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1513 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1514 D3DPSREGISTER_ScreenToDepth = 33,
1515 D3DPSREGISTER_ShadowMap_Parameters = 34,
1516 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1517 D3DPSREGISTER_SpecularPower = 36,
1518 D3DPSREGISTER_UserVec1 = 37,
1519 D3DPSREGISTER_UserVec2 = 38,
1520 D3DPSREGISTER_UserVec3 = 39,
1521 D3DPSREGISTER_UserVec4 = 40,
1522 D3DPSREGISTER_ViewTintColor = 41,
1523 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1524 D3DPSREGISTER_BloomColorSubtract = 43,
1525 D3DPSREGISTER_ViewToLight = 44, // float4x4
1526 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1527 D3DPSREGISTER_NormalmapScrollBlend = 52,
1528 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1529 D3DPSREGISTER_OffsetMapping_Bias = 54,
1534 /// information about each possible shader permutation
1535 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1536 /// currently selected permutation
1537 r_hlsl_permutation_t *r_hlsl_permutation;
1538 /// storage for permutations linked in the hash table
1539 memexpandablearray_t r_hlsl_permutationarray;
1541 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1543 //unsigned int hashdepth = 0;
1544 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1545 r_hlsl_permutation_t *p;
1546 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1548 if (p->mode == mode && p->permutation == permutation)
1550 //if (hashdepth > 10)
1551 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1556 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1558 p->permutation = permutation;
1559 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1560 r_hlsl_permutationhash[mode][hashindex] = p;
1561 //if (hashdepth > 10)
1562 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1567 //#include <d3dx9shader.h>
1568 //#include <d3dx9mesh.h>
1570 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1572 DWORD *vsbin = NULL;
1573 DWORD *psbin = NULL;
1574 fs_offset_t vsbinsize;
1575 fs_offset_t psbinsize;
1576 // IDirect3DVertexShader9 *vs = NULL;
1577 // IDirect3DPixelShader9 *ps = NULL;
1578 ID3DXBuffer *vslog = NULL;
1579 ID3DXBuffer *vsbuffer = NULL;
1580 ID3DXConstantTable *vsconstanttable = NULL;
1581 ID3DXBuffer *pslog = NULL;
1582 ID3DXBuffer *psbuffer = NULL;
1583 ID3DXConstantTable *psconstanttable = NULL;
1586 char temp[MAX_INPUTLINE];
1587 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1589 qboolean debugshader = gl_paranoid.integer != 0;
1590 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1591 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1594 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1595 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1597 if ((!vsbin && vertstring) || (!psbin && fragstring))
1599 const char* dllnames_d3dx9 [] =
1623 dllhandle_t d3dx9_dll = NULL;
1624 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1625 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1626 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1627 dllfunction_t d3dx9_dllfuncs[] =
1629 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1630 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1631 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1634 // 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...
1635 #ifndef ID3DXBuffer_GetBufferPointer
1636 #if !defined(__cplusplus) || defined(CINTERFACE)
1637 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1638 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1639 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1641 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1642 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1643 #define ID3DXBuffer_Release(p) (p)->Release()
1646 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1648 DWORD shaderflags = 0;
1650 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1651 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1652 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1653 if (vertstring && vertstring[0])
1657 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1658 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1661 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1664 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1665 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1666 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1667 ID3DXBuffer_Release(vsbuffer);
1671 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1672 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1673 ID3DXBuffer_Release(vslog);
1676 if (fragstring && fragstring[0])
1680 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1681 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1684 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1687 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1688 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1689 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1690 ID3DXBuffer_Release(psbuffer);
1694 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1695 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1696 ID3DXBuffer_Release(pslog);
1699 Sys_UnloadLibrary(&d3dx9_dll);
1702 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1706 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1707 if (FAILED(vsresult))
1708 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1709 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1710 if (FAILED(psresult))
1711 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1713 // free the shader data
1714 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1715 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1718 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1721 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1722 int vertstring_length = 0;
1723 int geomstring_length = 0;
1724 int fragstring_length = 0;
1727 char *vertstring, *geomstring, *fragstring;
1728 char permutationname[256];
1729 char cachename[256];
1730 int vertstrings_count = 0;
1731 int geomstrings_count = 0;
1732 int fragstrings_count = 0;
1733 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1734 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1735 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740 p->vertexshader = NULL;
1741 p->pixelshader = NULL;
1743 permutationname[0] = 0;
1745 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1747 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1748 strlcat(cachename, "hlsl/", sizeof(cachename));
1750 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1751 vertstrings_count = 0;
1752 geomstrings_count = 0;
1753 fragstrings_count = 0;
1754 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1755 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1756 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1758 // the first pretext is which type of shader to compile as
1759 // (later these will all be bound together as a program object)
1760 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1761 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1762 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1764 // the second pretext is the mode (for example a light source)
1765 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1766 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1767 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1768 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1769 strlcat(cachename, modeinfo->name, sizeof(cachename));
1771 // now add all the permutation pretexts
1772 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1774 if (permutation & (1ll<<i))
1776 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1777 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1778 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1779 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1780 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1784 // keep line numbers correct
1785 vertstrings_list[vertstrings_count++] = "\n";
1786 geomstrings_list[geomstrings_count++] = "\n";
1787 fragstrings_list[fragstrings_count++] = "\n";
1792 R_CompileShader_AddStaticParms(mode, permutation);
1793 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794 vertstrings_count += shaderstaticparms_count;
1795 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1796 geomstrings_count += shaderstaticparms_count;
1797 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1798 fragstrings_count += shaderstaticparms_count;
1800 // replace spaces in the cachename with _ characters
1801 for (i = 0;cachename[i];i++)
1802 if (cachename[i] == ' ')
1805 // now append the shader text itself
1806 vertstrings_list[vertstrings_count++] = sourcestring;
1807 geomstrings_list[geomstrings_count++] = sourcestring;
1808 fragstrings_list[fragstrings_count++] = sourcestring;
1810 vertstring_length = 0;
1811 for (i = 0;i < vertstrings_count;i++)
1812 vertstring_length += (int)strlen(vertstrings_list[i]);
1813 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1814 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1815 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1817 geomstring_length = 0;
1818 for (i = 0;i < geomstrings_count;i++)
1819 geomstring_length += (int)strlen(geomstrings_list[i]);
1820 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1821 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1822 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1824 fragstring_length = 0;
1825 for (i = 0;i < fragstrings_count;i++)
1826 fragstring_length += (int)strlen(fragstrings_list[i]);
1827 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1828 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1829 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1831 // try to load the cached shader, or generate one
1832 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1834 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1835 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1837 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1841 Mem_Free(vertstring);
1843 Mem_Free(geomstring);
1845 Mem_Free(fragstring);
1847 Mem_Free(sourcestring);
1850 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1851 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1852 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);}
1853 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);}
1854 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);}
1855 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);}
1857 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1858 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1859 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);}
1860 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);}
1861 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);}
1862 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);}
1864 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1866 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1867 if (r_hlsl_permutation != perm)
1869 r_hlsl_permutation = perm;
1870 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1872 if (!r_hlsl_permutation->compiled)
1873 R_HLSL_CompilePermutation(perm, mode, permutation);
1874 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1876 // remove features until we find a valid permutation
1878 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1880 // reduce i more quickly whenever it would not remove any bits
1881 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1882 if (!(permutation & j))
1885 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1886 if (!r_hlsl_permutation->compiled)
1887 R_HLSL_CompilePermutation(perm, mode, permutation);
1888 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1891 if (i >= SHADERPERMUTATION_COUNT)
1893 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1894 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1895 return; // no bit left to clear, entire mode is broken
1899 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1900 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1902 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1903 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1904 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1908 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1910 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1911 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1912 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1913 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1916 void R_GLSL_Restart_f(void)
1918 unsigned int i, limit;
1919 switch(vid.renderpath)
1921 case RENDERPATH_D3D9:
1924 r_hlsl_permutation_t *p;
1925 r_hlsl_permutation = NULL;
1926 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1927 for (i = 0;i < limit;i++)
1929 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1931 if (p->vertexshader)
1932 IDirect3DVertexShader9_Release(p->vertexshader);
1934 IDirect3DPixelShader9_Release(p->pixelshader);
1935 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1938 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1942 case RENDERPATH_D3D10:
1943 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945 case RENDERPATH_D3D11:
1946 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948 case RENDERPATH_GL20:
1949 case RENDERPATH_GLES2:
1951 r_glsl_permutation_t *p;
1952 r_glsl_permutation = NULL;
1953 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1954 for (i = 0;i < limit;i++)
1956 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1958 GL_Backend_FreeProgram(p->program);
1959 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1962 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1965 case RENDERPATH_GL11:
1966 case RENDERPATH_GL13:
1967 case RENDERPATH_GLES1:
1969 case RENDERPATH_SOFT:
1974 static void R_GLSL_DumpShader_f(void)
1976 int i, language, mode, dupe;
1978 shadermodeinfo_t *modeinfo;
1981 for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1983 modeinfo = shadermodeinfo[language];
1984 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1986 // don't dump the same file multiple times (most or all shaders come from the same file)
1987 for (dupe = mode - 1;dupe >= 0;dupe--)
1988 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1992 text = modeinfo[mode].builtinstring;
1995 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1998 FS_Print(file, "/* The engine may define the following macros:\n");
1999 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2000 for (i = 0;i < SHADERMODE_COUNT;i++)
2001 FS_Print(file, modeinfo[i].pretext);
2002 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2003 FS_Print(file, shaderpermutationinfo[i].pretext);
2004 FS_Print(file, "*/\n");
2005 FS_Print(file, text);
2007 Con_Printf("%s written\n", modeinfo[mode].filename);
2010 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2015 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2017 dpuint64 permutation = 0;
2018 if (r_trippy.integer && !notrippy)
2019 permutation |= SHADERPERMUTATION_TRIPPY;
2020 permutation |= SHADERPERMUTATION_VIEWTINT;
2022 permutation |= SHADERPERMUTATION_DIFFUSE;
2024 permutation |= SHADERPERMUTATION_SPECULAR;
2025 if (texturemode == GL_MODULATE)
2026 permutation |= SHADERPERMUTATION_COLORMAPPING;
2027 else if (texturemode == GL_ADD)
2028 permutation |= SHADERPERMUTATION_GLOW;
2029 else if (texturemode == GL_DECAL)
2030 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2031 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2032 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2033 if (suppresstexalpha)
2034 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2036 texturemode = GL_MODULATE;
2037 if (vid.allowalphatocoverage)
2038 GL_AlphaToCoverage(false);
2039 switch (vid.renderpath)
2041 case RENDERPATH_D3D9:
2043 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2044 R_Mesh_TexBind(GL20TU_FIRST , first );
2045 R_Mesh_TexBind(GL20TU_SECOND, second);
2046 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2047 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2050 case RENDERPATH_D3D10:
2051 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2053 case RENDERPATH_D3D11:
2054 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2056 case RENDERPATH_GL20:
2057 case RENDERPATH_GLES2:
2058 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2059 if (r_glsl_permutation->tex_Texture_First >= 0)
2060 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2061 if (r_glsl_permutation->tex_Texture_Second >= 0)
2062 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2063 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2064 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2066 case RENDERPATH_GL13:
2067 case RENDERPATH_GLES1:
2068 R_Mesh_TexBind(0, first );
2069 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2070 R_Mesh_TexMatrix(0, NULL);
2071 R_Mesh_TexBind(1, second);
2074 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2075 R_Mesh_TexMatrix(1, NULL);
2078 case RENDERPATH_GL11:
2079 R_Mesh_TexBind(0, first );
2080 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2081 R_Mesh_TexMatrix(0, NULL);
2083 case RENDERPATH_SOFT:
2084 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2085 R_Mesh_TexBind(GL20TU_FIRST , first );
2086 R_Mesh_TexBind(GL20TU_SECOND, second);
2091 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2093 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2096 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2098 dpuint64 permutation = 0;
2099 if (r_trippy.integer && !notrippy)
2100 permutation |= SHADERPERMUTATION_TRIPPY;
2102 permutation |= SHADERPERMUTATION_DEPTHRGB;
2104 permutation |= SHADERPERMUTATION_SKELETAL;
2106 if (vid.allowalphatocoverage)
2107 GL_AlphaToCoverage(false);
2108 switch (vid.renderpath)
2110 case RENDERPATH_D3D9:
2112 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2115 case RENDERPATH_D3D10:
2116 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2118 case RENDERPATH_D3D11:
2119 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2121 case RENDERPATH_GL20:
2122 case RENDERPATH_GLES2:
2123 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2124 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2125 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);
2128 case RENDERPATH_GL13:
2129 case RENDERPATH_GLES1:
2130 R_Mesh_TexBind(0, 0);
2131 R_Mesh_TexBind(1, 0);
2133 case RENDERPATH_GL11:
2134 R_Mesh_TexBind(0, 0);
2136 case RENDERPATH_SOFT:
2137 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2142 extern qboolean r_shadow_usingdeferredprepass;
2143 extern rtexture_t *r_shadow_attenuationgradienttexture;
2144 extern rtexture_t *r_shadow_attenuation2dtexture;
2145 extern rtexture_t *r_shadow_attenuation3dtexture;
2146 extern qboolean r_shadow_usingshadowmap2d;
2147 extern qboolean r_shadow_usingshadowmaportho;
2148 extern float r_shadow_modelshadowmap_texturescale[4];
2149 extern float r_shadow_modelshadowmap_parameters[4];
2150 extern float r_shadow_lightshadowmap_texturescale[4];
2151 extern float r_shadow_lightshadowmap_parameters[4];
2152 extern qboolean r_shadow_shadowmapvsdct;
2153 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2154 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2155 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2156 extern matrix4x4_t r_shadow_shadowmapmatrix;
2157 extern int r_shadow_prepass_width;
2158 extern int r_shadow_prepass_height;
2159 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2160 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2161 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2162 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2164 #define BLENDFUNC_ALLOWS_COLORMOD 1
2165 #define BLENDFUNC_ALLOWS_FOG 2
2166 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2167 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2168 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2169 static int R_BlendFuncFlags(int src, int dst)
2173 // a blendfunc allows colormod if:
2174 // a) it can never keep the destination pixel invariant, or
2175 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2176 // this is to prevent unintended side effects from colormod
2178 // a blendfunc allows fog if:
2179 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2180 // this is to prevent unintended side effects from fog
2182 // these checks are the output of fogeval.pl
2184 r |= BLENDFUNC_ALLOWS_COLORMOD;
2185 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2186 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2187 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2188 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2189 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2190 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2191 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2193 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2194 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2195 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2196 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2197 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2198 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2199 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2200 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2201 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2202 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2204 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2205 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2210 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)
2212 // select a permutation of the lighting shader appropriate to this
2213 // combination of texture, entity, light source, and fogging, only use the
2214 // minimum features necessary to avoid wasting rendering time in the
2215 // fragment shader on features that are not being used
2216 dpuint64 permutation = 0;
2217 unsigned int mode = 0;
2219 static float dummy_colormod[3] = {1, 1, 1};
2220 float *colormod = rsurface.colormod;
2222 matrix4x4_t tempmatrix;
2223 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2224 if (r_trippy.integer && !notrippy)
2225 permutation |= SHADERPERMUTATION_TRIPPY;
2226 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2227 permutation |= SHADERPERMUTATION_ALPHAKILL;
2228 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2229 permutation |= SHADERPERMUTATION_OCCLUDE;
2230 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2231 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2232 if (rsurfacepass == RSURFPASS_BACKGROUND)
2234 // distorted background
2235 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2237 mode = SHADERMODE_WATER;
2238 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2239 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2240 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2242 // this is the right thing to do for wateralpha
2243 GL_BlendFunc(GL_ONE, GL_ZERO);
2244 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2248 // this is the right thing to do for entity alpha
2249 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2250 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2253 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2255 mode = SHADERMODE_REFRACTION;
2256 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2257 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2258 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2259 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2263 mode = SHADERMODE_GENERIC;
2264 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2265 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2266 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2268 if (vid.allowalphatocoverage)
2269 GL_AlphaToCoverage(false);
2271 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2273 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2275 switch(rsurface.texture->offsetmapping)
2277 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2278 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2279 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2280 case OFFSETMAPPING_OFF: break;
2283 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2284 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2285 // normalmap (deferred prepass), may use alpha test on diffuse
2286 mode = SHADERMODE_DEFERREDGEOMETRY;
2287 GL_BlendFunc(GL_ONE, GL_ZERO);
2288 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2289 if (vid.allowalphatocoverage)
2290 GL_AlphaToCoverage(false);
2292 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2294 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2296 switch(rsurface.texture->offsetmapping)
2298 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2299 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301 case OFFSETMAPPING_OFF: break;
2304 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2305 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2306 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2307 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2309 mode = SHADERMODE_LIGHTSOURCE;
2310 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2311 permutation |= SHADERPERMUTATION_CUBEFILTER;
2312 if (diffusescale > 0)
2313 permutation |= SHADERPERMUTATION_DIFFUSE;
2314 if (specularscale > 0)
2315 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2316 if (r_refdef.fogenabled)
2317 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2318 if (rsurface.texture->colormapping)
2319 permutation |= SHADERPERMUTATION_COLORMAPPING;
2320 if (r_shadow_usingshadowmap2d)
2322 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2323 if(r_shadow_shadowmapvsdct)
2324 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2326 if (r_shadow_shadowmap2ddepthbuffer)
2327 permutation |= SHADERPERMUTATION_DEPTHRGB;
2329 if (rsurface.texture->reflectmasktexture)
2330 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2331 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2332 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2333 if (vid.allowalphatocoverage)
2334 GL_AlphaToCoverage(false);
2336 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2338 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2340 switch(rsurface.texture->offsetmapping)
2342 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2343 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2344 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345 case OFFSETMAPPING_OFF: break;
2348 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2349 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2350 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2351 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2352 // unshaded geometry (fullbright or ambient model lighting)
2353 mode = SHADERMODE_FLATCOLOR;
2354 ambientscale = diffusescale = specularscale = 0;
2355 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2356 permutation |= SHADERPERMUTATION_GLOW;
2357 if (r_refdef.fogenabled)
2358 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2359 if (rsurface.texture->colormapping)
2360 permutation |= SHADERPERMUTATION_COLORMAPPING;
2361 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2363 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2364 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2366 if (r_shadow_shadowmap2ddepthbuffer)
2367 permutation |= SHADERPERMUTATION_DEPTHRGB;
2369 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2370 permutation |= SHADERPERMUTATION_REFLECTION;
2371 if (rsurface.texture->reflectmasktexture)
2372 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2373 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2374 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2375 // when using alphatocoverage, we don't need alphakill
2376 if (vid.allowalphatocoverage)
2378 if (r_transparent_alphatocoverage.integer)
2380 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2381 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2384 GL_AlphaToCoverage(false);
2387 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2389 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2391 switch(rsurface.texture->offsetmapping)
2393 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2394 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2395 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2396 case OFFSETMAPPING_OFF: break;
2399 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2400 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2401 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2402 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2403 // directional model lighting
2404 mode = SHADERMODE_LIGHTDIRECTION;
2405 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2406 permutation |= SHADERPERMUTATION_GLOW;
2407 permutation |= SHADERPERMUTATION_DIFFUSE;
2408 if (specularscale > 0)
2409 permutation |= SHADERPERMUTATION_SPECULAR;
2410 if (r_refdef.fogenabled)
2411 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2412 if (rsurface.texture->colormapping)
2413 permutation |= SHADERPERMUTATION_COLORMAPPING;
2414 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2416 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2417 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2419 if (r_shadow_shadowmap2ddepthbuffer)
2420 permutation |= SHADERPERMUTATION_DEPTHRGB;
2422 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2423 permutation |= SHADERPERMUTATION_REFLECTION;
2424 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2425 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2426 if (rsurface.texture->reflectmasktexture)
2427 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2428 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2430 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2431 if (r_shadow_bouncegrid_state.directional)
2432 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2434 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2435 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2436 // when using alphatocoverage, we don't need alphakill
2437 if (vid.allowalphatocoverage)
2439 if (r_transparent_alphatocoverage.integer)
2441 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2442 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2445 GL_AlphaToCoverage(false);
2448 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2450 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2452 switch(rsurface.texture->offsetmapping)
2454 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2455 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2456 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2457 case OFFSETMAPPING_OFF: break;
2460 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2461 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2462 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2463 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2464 // ambient model lighting
2465 mode = SHADERMODE_LIGHTDIRECTION;
2466 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2467 permutation |= SHADERPERMUTATION_GLOW;
2468 if (r_refdef.fogenabled)
2469 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2470 if (rsurface.texture->colormapping)
2471 permutation |= SHADERPERMUTATION_COLORMAPPING;
2472 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2474 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2475 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2477 if (r_shadow_shadowmap2ddepthbuffer)
2478 permutation |= SHADERPERMUTATION_DEPTHRGB;
2480 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2481 permutation |= SHADERPERMUTATION_REFLECTION;
2482 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2483 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2484 if (rsurface.texture->reflectmasktexture)
2485 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2486 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2488 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2489 if (r_shadow_bouncegrid_state.directional)
2490 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2492 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2493 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494 // when using alphatocoverage, we don't need alphakill
2495 if (vid.allowalphatocoverage)
2497 if (r_transparent_alphatocoverage.integer)
2499 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2500 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2503 GL_AlphaToCoverage(false);
2508 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2510 switch(rsurface.texture->offsetmapping)
2512 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2513 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2514 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2515 case OFFSETMAPPING_OFF: break;
2518 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2519 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2520 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2521 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2523 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2524 permutation |= SHADERPERMUTATION_GLOW;
2525 if (r_refdef.fogenabled)
2526 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2527 if (rsurface.texture->colormapping)
2528 permutation |= SHADERPERMUTATION_COLORMAPPING;
2529 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2531 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2532 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2534 if (r_shadow_shadowmap2ddepthbuffer)
2535 permutation |= SHADERPERMUTATION_DEPTHRGB;
2537 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2538 permutation |= SHADERPERMUTATION_REFLECTION;
2539 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2540 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2541 if (rsurface.texture->reflectmasktexture)
2542 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2543 if (FAKELIGHT_ENABLED)
2545 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2546 mode = SHADERMODE_FAKELIGHT;
2547 permutation |= SHADERPERMUTATION_DIFFUSE;
2548 if (specularscale > 0)
2549 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2551 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2553 // deluxemapping (light direction texture)
2554 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2555 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2557 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2558 permutation |= SHADERPERMUTATION_DIFFUSE;
2559 if (specularscale > 0)
2560 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2562 else if (r_glsl_deluxemapping.integer >= 2)
2564 // fake deluxemapping (uniform light direction in tangentspace)
2565 if (rsurface.uselightmaptexture)
2566 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2568 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2569 permutation |= SHADERPERMUTATION_DIFFUSE;
2570 if (specularscale > 0)
2571 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2573 else if (rsurface.uselightmaptexture)
2575 // ordinary lightmapping (q1bsp, q3bsp)
2576 mode = SHADERMODE_LIGHTMAP;
2580 // ordinary vertex coloring (q3bsp)
2581 mode = SHADERMODE_VERTEXCOLOR;
2583 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2585 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2586 if (r_shadow_bouncegrid_state.directional)
2587 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2589 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2590 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2591 // when using alphatocoverage, we don't need alphakill
2592 if (vid.allowalphatocoverage)
2594 if (r_transparent_alphatocoverage.integer)
2596 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2597 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2600 GL_AlphaToCoverage(false);
2603 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2604 colormod = dummy_colormod;
2605 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2606 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2607 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2608 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2609 switch(vid.renderpath)
2611 case RENDERPATH_D3D9:
2613 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);
2614 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2615 R_SetupShader_SetPermutationHLSL(mode, permutation);
2616 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2617 if (mode == SHADERMODE_LIGHTSOURCE)
2619 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2620 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2624 if (mode == SHADERMODE_LIGHTDIRECTION)
2626 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2629 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2630 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2631 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2632 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2633 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2635 if (mode == SHADERMODE_LIGHTSOURCE)
2637 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2638 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2639 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2640 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2641 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2643 // additive passes are only darkened by fog, not tinted
2644 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2645 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2649 if (mode == SHADERMODE_FLATCOLOR)
2651 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2653 else if (mode == SHADERMODE_LIGHTDIRECTION)
2655 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]);
2656 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2657 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);
2658 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2659 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2660 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2661 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2665 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2666 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2667 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);
2668 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2669 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2671 // additive passes are only darkened by fog, not tinted
2672 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2673 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2675 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2676 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);
2677 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2678 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2679 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2680 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2681 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2682 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2683 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2684 if (mode == SHADERMODE_WATER)
2685 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2687 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2689 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2690 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2694 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2695 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2697 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2698 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));
2699 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2700 if (rsurface.texture->pantstexture)
2701 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2703 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2704 if (rsurface.texture->shirttexture)
2705 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2707 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2708 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2709 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2710 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2711 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2712 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2713 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2714 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2715 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2716 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2718 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2719 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2720 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2721 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2723 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2724 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2725 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2726 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2727 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2728 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2729 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2730 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2731 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2732 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2733 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2734 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2735 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2736 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2737 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2738 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2739 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2740 if (rsurfacepass == RSURFPASS_BACKGROUND)
2742 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2743 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2744 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2748 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2750 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2751 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2752 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2753 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2755 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2756 if (rsurface.rtlight)
2758 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2759 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2764 case RENDERPATH_D3D10:
2765 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2767 case RENDERPATH_D3D11:
2768 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2770 case RENDERPATH_GL20:
2771 case RENDERPATH_GLES2:
2772 if (!vid.useinterleavedarrays)
2774 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);
2775 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2776 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2777 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2778 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2779 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2780 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2781 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2782 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2783 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2784 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2788 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);
2789 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2791 // this has to be after RSurf_PrepareVerticesForBatch
2792 if (rsurface.batchskeletaltransform3x4buffer)
2793 permutation |= SHADERPERMUTATION_SKELETAL;
2794 R_SetupShader_SetPermutationGLSL(mode, permutation);
2795 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2796 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);
2798 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2799 if (mode == SHADERMODE_LIGHTSOURCE)
2801 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2802 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2803 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2804 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2805 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2806 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);
2808 // additive passes are only darkened by fog, not tinted
2809 if (r_glsl_permutation->loc_FogColor >= 0)
2810 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2811 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);
2815 if (mode == SHADERMODE_FLATCOLOR)
2817 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2819 else if (mode == SHADERMODE_LIGHTDIRECTION)
2821 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]);
2822 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]);
2823 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);
2824 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2825 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2826 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]);
2827 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]);
2831 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]);
2832 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]);
2833 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);
2834 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2835 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2837 // additive passes are only darkened by fog, not tinted
2838 if (r_glsl_permutation->loc_FogColor >= 0)
2840 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2841 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2843 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2845 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);
2846 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]);
2847 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]);
2848 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]);
2849 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]);
2850 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2851 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2852 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);
2853 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]);
2855 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2856 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2857 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2858 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2860 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]);
2861 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]);
2865 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]);
2866 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]);
2869 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2870 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));
2871 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2872 if (r_glsl_permutation->loc_Color_Pants >= 0)
2874 if (rsurface.texture->pantstexture)
2875 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2877 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2879 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2881 if (rsurface.texture->shirttexture)
2882 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2884 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2886 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]);
2887 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2888 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2889 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2890 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2891 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2892 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2893 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2894 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2896 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);
2897 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2898 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]);
2899 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2900 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);}
2901 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2903 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2904 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2905 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2906 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2907 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2908 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2909 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2910 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2911 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2912 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2913 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2914 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2915 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2916 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2917 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);
2918 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2919 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2920 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2921 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2922 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2923 if (rsurfacepass == RSURFPASS_BACKGROUND)
2925 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);
2926 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);
2927 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);
2931 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);
2933 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2934 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2935 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2936 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2938 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2939 if (rsurface.rtlight)
2941 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2942 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2945 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2948 case RENDERPATH_GL11:
2949 case RENDERPATH_GL13:
2950 case RENDERPATH_GLES1:
2952 case RENDERPATH_SOFT:
2953 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);
2954 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2955 R_SetupShader_SetPermutationSoft(mode, permutation);
2956 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2957 if (mode == SHADERMODE_LIGHTSOURCE)
2959 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2960 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2961 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2962 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2963 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2964 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2966 // additive passes are only darkened by fog, not tinted
2967 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2968 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2972 if (mode == SHADERMODE_FLATCOLOR)
2974 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2976 else if (mode == SHADERMODE_LIGHTDIRECTION)
2978 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]);
2979 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2980 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);
2981 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2982 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2983 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]);
2984 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2988 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2989 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2990 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);
2991 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2992 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2994 // additive passes are only darkened by fog, not tinted
2995 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2996 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2998 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2999 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);
3000 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]);
3001 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]);
3002 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]);
3003 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]);
3004 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3005 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
3006 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3007 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3009 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3010 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3011 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3012 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3014 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]);
3015 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]);
3019 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]);
3020 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]);
3023 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3024 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));
3025 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3026 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3028 if (rsurface.texture->pantstexture)
3029 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3031 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3033 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3035 if (rsurface.texture->shirttexture)
3036 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3038 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3040 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3041 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3042 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3043 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3044 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3045 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3046 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3047 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3048 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3050 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3051 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3052 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3053 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3055 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3056 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3057 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3058 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3059 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3060 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3061 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3062 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3063 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3064 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3065 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3066 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3067 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3068 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3069 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3070 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3071 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3072 if (rsurfacepass == RSURFPASS_BACKGROUND)
3074 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3075 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3076 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3080 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3082 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3083 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3084 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3085 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3087 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3088 if (rsurface.rtlight)
3090 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3091 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3098 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3100 // select a permutation of the lighting shader appropriate to this
3101 // combination of texture, entity, light source, and fogging, only use the
3102 // minimum features necessary to avoid wasting rendering time in the
3103 // fragment shader on features that are not being used
3104 dpuint64 permutation = 0;
3105 unsigned int mode = 0;
3106 const float *lightcolorbase = rtlight->currentcolor;
3107 float ambientscale = rtlight->ambientscale;
3108 float diffusescale = rtlight->diffusescale;
3109 float specularscale = rtlight->specularscale;
3110 // this is the location of the light in view space
3111 vec3_t viewlightorigin;
3112 // this transforms from view space (camera) to light space (cubemap)
3113 matrix4x4_t viewtolight;
3114 matrix4x4_t lighttoview;
3115 float viewtolight16f[16];
3117 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3118 if (rtlight->currentcubemap != r_texture_whitecube)
3119 permutation |= SHADERPERMUTATION_CUBEFILTER;
3120 if (diffusescale > 0)
3121 permutation |= SHADERPERMUTATION_DIFFUSE;
3122 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3123 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3124 if (r_shadow_usingshadowmap2d)
3126 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3127 if (r_shadow_shadowmapvsdct)
3128 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3130 if (r_shadow_shadowmap2ddepthbuffer)
3131 permutation |= SHADERPERMUTATION_DEPTHRGB;
3133 if (vid.allowalphatocoverage)
3134 GL_AlphaToCoverage(false);
3135 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3136 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3137 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3138 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3139 switch(vid.renderpath)
3141 case RENDERPATH_D3D9:
3143 R_SetupShader_SetPermutationHLSL(mode, permutation);
3144 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3145 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3146 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3147 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3148 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3149 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3150 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3151 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);
3152 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3153 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3155 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3156 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3157 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3158 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3159 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3162 case RENDERPATH_D3D10:
3163 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3165 case RENDERPATH_D3D11:
3166 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3168 case RENDERPATH_GL20:
3169 case RENDERPATH_GLES2:
3170 R_SetupShader_SetPermutationGLSL(mode, permutation);
3171 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3172 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3173 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3174 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3175 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3176 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]);
3177 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]);
3178 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);
3179 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]);
3180 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3182 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3183 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3184 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3185 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3186 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3188 case RENDERPATH_GL11:
3189 case RENDERPATH_GL13:
3190 case RENDERPATH_GLES1:
3192 case RENDERPATH_SOFT:
3193 R_SetupShader_SetPermutationGLSL(mode, permutation);
3194 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3195 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3196 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3197 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3198 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3199 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]);
3200 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]);
3201 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);
3202 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3203 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3205 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3206 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3207 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3208 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3209 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3214 #define SKINFRAME_HASH 1024
3218 unsigned int loadsequence; // incremented each level change
3219 memexpandablearray_t array;
3220 skinframe_t *hash[SKINFRAME_HASH];
3223 r_skinframe_t r_skinframe;
3225 void R_SkinFrame_PrepareForPurge(void)
3227 r_skinframe.loadsequence++;
3228 // wrap it without hitting zero
3229 if (r_skinframe.loadsequence >= 200)
3230 r_skinframe.loadsequence = 1;
3233 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3237 // mark the skinframe as used for the purging code
3238 skinframe->loadsequence = r_skinframe.loadsequence;
3241 void R_SkinFrame_Purge(void)
3245 for (i = 0;i < SKINFRAME_HASH;i++)
3247 for (s = r_skinframe.hash[i];s;s = s->next)
3249 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3251 if (s->merged == s->base)
3253 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3254 R_PurgeTexture(s->stain );s->stain = NULL;
3255 R_PurgeTexture(s->merged);s->merged = NULL;
3256 R_PurgeTexture(s->base );s->base = NULL;
3257 R_PurgeTexture(s->pants );s->pants = NULL;
3258 R_PurgeTexture(s->shirt );s->shirt = NULL;
3259 R_PurgeTexture(s->nmap );s->nmap = NULL;
3260 R_PurgeTexture(s->gloss );s->gloss = NULL;
3261 R_PurgeTexture(s->glow );s->glow = NULL;
3262 R_PurgeTexture(s->fog );s->fog = NULL;
3263 R_PurgeTexture(s->reflect);s->reflect = NULL;
3264 s->loadsequence = 0;
3270 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3272 char basename[MAX_QPATH];
3274 Image_StripImageExtension(name, basename, sizeof(basename));
3276 if( last == NULL ) {
3278 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3279 item = r_skinframe.hash[hashindex];
3284 // linearly search through the hash bucket
3285 for( ; item ; item = item->next ) {
3286 if( !strcmp( item->basename, basename ) ) {
3293 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3297 char basename[MAX_QPATH];
3299 Image_StripImageExtension(name, basename, sizeof(basename));
3301 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3302 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3303 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3307 rtexture_t *dyntexture;
3308 // check whether its a dynamic texture
3309 dyntexture = CL_GetDynTexture( basename );
3310 if (!add && !dyntexture)
3312 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3313 memset(item, 0, sizeof(*item));
3314 strlcpy(item->basename, basename, sizeof(item->basename));
3315 item->base = dyntexture; // either NULL or dyntexture handle
3316 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3317 item->comparewidth = comparewidth;
3318 item->compareheight = compareheight;
3319 item->comparecrc = comparecrc;
3320 item->next = r_skinframe.hash[hashindex];
3321 r_skinframe.hash[hashindex] = item;
3323 else if (textureflags & TEXF_FORCE_RELOAD)
3325 rtexture_t *dyntexture;
3326 // check whether its a dynamic texture
3327 dyntexture = CL_GetDynTexture( basename );
3328 if (!add && !dyntexture)
3330 if (item->merged == item->base)
3331 item->merged = NULL;
3332 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3333 R_PurgeTexture(item->stain );item->stain = NULL;
3334 R_PurgeTexture(item->merged);item->merged = NULL;
3335 R_PurgeTexture(item->base );item->base = NULL;
3336 R_PurgeTexture(item->pants );item->pants = NULL;
3337 R_PurgeTexture(item->shirt );item->shirt = NULL;
3338 R_PurgeTexture(item->nmap );item->nmap = NULL;
3339 R_PurgeTexture(item->gloss );item->gloss = NULL;
3340 R_PurgeTexture(item->glow );item->glow = NULL;
3341 R_PurgeTexture(item->fog );item->fog = NULL;
3342 R_PurgeTexture(item->reflect);item->reflect = NULL;
3343 item->loadsequence = 0;
3345 else if( item->base == NULL )
3347 rtexture_t *dyntexture;
3348 // check whether its a dynamic texture
3349 // 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]
3350 dyntexture = CL_GetDynTexture( basename );
3351 item->base = dyntexture; // either NULL or dyntexture handle
3354 R_SkinFrame_MarkUsed(item);
3358 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3360 unsigned long long avgcolor[5], wsum; \
3368 for(pix = 0; pix < cnt; ++pix) \
3371 for(comp = 0; comp < 3; ++comp) \
3373 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3376 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3378 for(comp = 0; comp < 3; ++comp) \
3379 avgcolor[comp] += getpixel * w; \
3382 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3383 avgcolor[4] += getpixel; \
3385 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3387 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3388 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3389 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3390 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3393 extern cvar_t gl_picmip;
3394 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3397 unsigned char *pixels;
3398 unsigned char *bumppixels;
3399 unsigned char *basepixels = NULL;
3400 int basepixels_width = 0;
3401 int basepixels_height = 0;
3402 skinframe_t *skinframe;
3403 rtexture_t *ddsbase = NULL;
3404 qboolean ddshasalpha = false;
3405 float ddsavgcolor[4];
3406 char basename[MAX_QPATH];
3407 int miplevel = R_PicmipForFlags(textureflags);
3408 int savemiplevel = miplevel;
3412 if (cls.state == ca_dedicated)
3415 // return an existing skinframe if already loaded
3416 // if loading of the first image fails, don't make a new skinframe as it
3417 // would cause all future lookups of this to be missing
3418 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3419 if (skinframe && skinframe->base)
3422 Image_StripImageExtension(name, basename, sizeof(basename));
3424 // check for DDS texture file first
3425 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3427 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3428 if (basepixels == NULL)
3432 // FIXME handle miplevel
3434 if (developer_loading.integer)
3435 Con_Printf("loading skin \"%s\"\n", name);
3437 // we've got some pixels to store, so really allocate this new texture now
3439 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3440 textureflags &= ~TEXF_FORCE_RELOAD;
3441 skinframe->stain = NULL;
3442 skinframe->merged = NULL;
3443 skinframe->base = NULL;
3444 skinframe->pants = NULL;
3445 skinframe->shirt = NULL;
3446 skinframe->nmap = NULL;
3447 skinframe->gloss = NULL;
3448 skinframe->glow = NULL;
3449 skinframe->fog = NULL;
3450 skinframe->reflect = NULL;
3451 skinframe->hasalpha = false;
3452 // we could store the q2animname here too
3456 skinframe->base = ddsbase;
3457 skinframe->hasalpha = ddshasalpha;
3458 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3459 if (r_loadfog && skinframe->hasalpha)
3460 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);
3461 //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]);
3465 basepixels_width = image_width;
3466 basepixels_height = image_height;
3467 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);
3468 if (textureflags & TEXF_ALPHA)
3470 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3472 if (basepixels[j] < 255)
3474 skinframe->hasalpha = true;
3478 if (r_loadfog && skinframe->hasalpha)
3480 // has transparent pixels
3481 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3482 for (j = 0;j < image_width * image_height * 4;j += 4)
3487 pixels[j+3] = basepixels[j+3];
3489 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);
3493 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3495 //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]);
3496 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3497 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3498 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3499 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3505 mymiplevel = savemiplevel;
3506 if (r_loadnormalmap)
3507 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);
3508 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3510 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3511 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3512 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3513 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3516 // _norm is the name used by tenebrae and has been adopted as standard
3517 if (r_loadnormalmap && skinframe->nmap == NULL)
3519 mymiplevel = savemiplevel;
3520 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3522 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);
3526 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3528 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3529 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3530 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);
3532 Mem_Free(bumppixels);
3534 else if (r_shadow_bumpscale_basetexture.value > 0)
3536 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3537 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3538 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);
3542 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3543 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3547 // _luma is supported only for tenebrae compatibility
3548 // _glow is the preferred name
3549 mymiplevel = savemiplevel;
3550 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))))
3552 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);
3554 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3555 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3557 Mem_Free(pixels);pixels = NULL;
3560 mymiplevel = savemiplevel;
3561 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3563 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);
3565 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3566 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3572 mymiplevel = savemiplevel;
3573 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3575 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);
3577 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3578 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3584 mymiplevel = savemiplevel;
3585 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3587 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);
3589 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3590 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3596 mymiplevel = savemiplevel;
3597 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3599 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);
3601 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3602 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3609 Mem_Free(basepixels);
3614 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3615 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3618 skinframe_t *skinframe;
3621 if (cls.state == ca_dedicated)
3624 // if already loaded just return it, otherwise make a new skinframe
3625 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3626 if (skinframe->base)
3628 textureflags &= ~TEXF_FORCE_RELOAD;
3630 skinframe->stain = NULL;
3631 skinframe->merged = NULL;
3632 skinframe->base = NULL;
3633 skinframe->pants = NULL;
3634 skinframe->shirt = NULL;
3635 skinframe->nmap = NULL;
3636 skinframe->gloss = NULL;
3637 skinframe->glow = NULL;
3638 skinframe->fog = NULL;
3639 skinframe->reflect = NULL;
3640 skinframe->hasalpha = false;
3642 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3646 if (developer_loading.integer)
3647 Con_Printf("loading 32bit skin \"%s\"\n", name);
3649 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3651 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3652 unsigned char *b = a + width * height * 4;
3653 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3654 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);
3657 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3658 if (textureflags & TEXF_ALPHA)
3660 for (i = 3;i < width * height * 4;i += 4)
3662 if (skindata[i] < 255)
3664 skinframe->hasalpha = true;
3668 if (r_loadfog && skinframe->hasalpha)
3670 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3671 memcpy(fogpixels, skindata, width * height * 4);
3672 for (i = 0;i < width * height * 4;i += 4)
3673 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3674 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3675 Mem_Free(fogpixels);
3679 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3680 //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]);
3685 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3689 skinframe_t *skinframe;
3691 if (cls.state == ca_dedicated)
3694 // if already loaded just return it, otherwise make a new skinframe
3695 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3696 if (skinframe->base)
3698 //textureflags &= ~TEXF_FORCE_RELOAD;
3700 skinframe->stain = NULL;
3701 skinframe->merged = NULL;
3702 skinframe->base = NULL;
3703 skinframe->pants = NULL;
3704 skinframe->shirt = NULL;
3705 skinframe->nmap = NULL;
3706 skinframe->gloss = NULL;
3707 skinframe->glow = NULL;
3708 skinframe->fog = NULL;
3709 skinframe->reflect = NULL;
3710 skinframe->hasalpha = false;
3712 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3716 if (developer_loading.integer)
3717 Con_Printf("loading quake skin \"%s\"\n", name);
3719 // 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)
3720 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3721 memcpy(skinframe->qpixels, skindata, width*height);
3722 skinframe->qwidth = width;
3723 skinframe->qheight = height;
3726 for (i = 0;i < width * height;i++)
3727 featuresmask |= palette_featureflags[skindata[i]];
3729 skinframe->hasalpha = false;
3732 skinframe->hasalpha = true;
3733 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3734 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3735 skinframe->qgeneratemerged = true;
3736 skinframe->qgeneratebase = skinframe->qhascolormapping;
3737 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3739 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3740 //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]);
3745 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3749 unsigned char *skindata;
3752 if (!skinframe->qpixels)
3755 if (!skinframe->qhascolormapping)
3756 colormapped = false;
3760 if (!skinframe->qgeneratebase)
3765 if (!skinframe->qgeneratemerged)
3769 width = skinframe->qwidth;
3770 height = skinframe->qheight;
3771 skindata = skinframe->qpixels;
3773 if (skinframe->qgeneratenmap)
3775 unsigned char *a, *b;
3776 skinframe->qgeneratenmap = false;
3777 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3778 b = a + width * height * 4;
3779 // use either a custom palette or the quake palette
3780 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3781 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3782 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);
3786 if (skinframe->qgenerateglow)
3788 skinframe->qgenerateglow = false;
3789 if (skinframe->hasalpha) // fence textures
3790 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
3792 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
3797 skinframe->qgeneratebase = false;
3798 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);
3799 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);
3800 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);
3804 skinframe->qgeneratemerged = false;
3805 if (skinframe->hasalpha) // fence textures
3806 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);
3808 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);
3811 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3813 Mem_Free(skinframe->qpixels);
3814 skinframe->qpixels = NULL;
3818 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)
3821 skinframe_t *skinframe;
3824 if (cls.state == ca_dedicated)
3827 // if already loaded just return it, otherwise make a new skinframe
3828 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3829 if (skinframe->base)
3831 textureflags &= ~TEXF_FORCE_RELOAD;
3833 skinframe->stain = NULL;
3834 skinframe->merged = NULL;
3835 skinframe->base = NULL;
3836 skinframe->pants = NULL;
3837 skinframe->shirt = NULL;
3838 skinframe->nmap = NULL;
3839 skinframe->gloss = NULL;
3840 skinframe->glow = NULL;
3841 skinframe->fog = NULL;
3842 skinframe->reflect = NULL;
3843 skinframe->hasalpha = false;
3845 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3849 if (developer_loading.integer)
3850 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3852 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3853 if (textureflags & TEXF_ALPHA)
3855 for (i = 0;i < width * height;i++)
3857 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3859 skinframe->hasalpha = true;
3863 if (r_loadfog && skinframe->hasalpha)
3864 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3867 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3868 //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]);
3873 skinframe_t *R_SkinFrame_LoadMissing(void)
3875 skinframe_t *skinframe;
3877 if (cls.state == ca_dedicated)
3880 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3881 skinframe->stain = NULL;
3882 skinframe->merged = NULL;
3883 skinframe->base = NULL;
3884 skinframe->pants = NULL;
3885 skinframe->shirt = NULL;
3886 skinframe->nmap = NULL;
3887 skinframe->gloss = NULL;
3888 skinframe->glow = NULL;
3889 skinframe->fog = NULL;
3890 skinframe->reflect = NULL;
3891 skinframe->hasalpha = false;
3893 skinframe->avgcolor[0] = rand() / RAND_MAX;
3894 skinframe->avgcolor[1] = rand() / RAND_MAX;
3895 skinframe->avgcolor[2] = rand() / RAND_MAX;
3896 skinframe->avgcolor[3] = 1;
3901 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3902 typedef struct suffixinfo_s
3905 qboolean flipx, flipy, flipdiagonal;
3908 static suffixinfo_t suffix[3][6] =
3911 {"px", false, false, false},
3912 {"nx", false, false, false},
3913 {"py", false, false, false},
3914 {"ny", false, false, false},
3915 {"pz", false, false, false},
3916 {"nz", false, false, false}
3919 {"posx", false, false, false},
3920 {"negx", false, false, false},
3921 {"posy", false, false, false},
3922 {"negy", false, false, false},
3923 {"posz", false, false, false},
3924 {"negz", false, false, false}
3927 {"rt", true, false, true},
3928 {"lf", false, true, true},
3929 {"ft", true, true, false},
3930 {"bk", false, false, false},
3931 {"up", true, false, true},
3932 {"dn", true, false, true}
3936 static int componentorder[4] = {0, 1, 2, 3};
3938 static rtexture_t *R_LoadCubemap(const char *basename)
3940 int i, j, cubemapsize;
3941 unsigned char *cubemappixels, *image_buffer;
3942 rtexture_t *cubemaptexture;
3944 // must start 0 so the first loadimagepixels has no requested width/height
3946 cubemappixels = NULL;
3947 cubemaptexture = NULL;
3948 // keep trying different suffix groups (posx, px, rt) until one loads
3949 for (j = 0;j < 3 && !cubemappixels;j++)
3951 // load the 6 images in the suffix group
3952 for (i = 0;i < 6;i++)
3954 // generate an image name based on the base and and suffix
3955 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3957 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3959 // an image loaded, make sure width and height are equal
3960 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3962 // if this is the first image to load successfully, allocate the cubemap memory
3963 if (!cubemappixels && image_width >= 1)
3965 cubemapsize = image_width;
3966 // note this clears to black, so unavailable sides are black
3967 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3969 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3971 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);
3974 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3976 Mem_Free(image_buffer);
3980 // if a cubemap loaded, upload it
3983 if (developer_loading.integer)
3984 Con_Printf("loading cubemap \"%s\"\n", basename);
3986 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);
3987 Mem_Free(cubemappixels);
3991 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3992 if (developer_loading.integer)
3994 Con_Printf("(tried tried images ");
3995 for (j = 0;j < 3;j++)
3996 for (i = 0;i < 6;i++)
3997 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3998 Con_Print(" and was unable to find any of them).\n");
4001 return cubemaptexture;
4004 rtexture_t *R_GetCubemap(const char *basename)
4007 for (i = 0;i < r_texture_numcubemaps;i++)
4008 if (r_texture_cubemaps[i] != NULL)
4009 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4010 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4011 if (i >= MAX_CUBEMAPS || !r_main_mempool)
4012 return r_texture_whitecube;
4013 r_texture_numcubemaps++;
4014 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4015 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4016 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4017 return r_texture_cubemaps[i]->texture;
4020 static void R_Main_FreeViewCache(void)
4022 if (r_refdef.viewcache.entityvisible)
4023 Mem_Free(r_refdef.viewcache.entityvisible);
4024 if (r_refdef.viewcache.world_pvsbits)
4025 Mem_Free(r_refdef.viewcache.world_pvsbits);
4026 if (r_refdef.viewcache.world_leafvisible)
4027 Mem_Free(r_refdef.viewcache.world_leafvisible);
4028 if (r_refdef.viewcache.world_surfacevisible)
4029 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4030 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4033 static void R_Main_ResizeViewCache(void)
4035 int numentities = r_refdef.scene.numentities;
4036 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4037 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4038 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4039 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4040 if (r_refdef.viewcache.maxentities < numentities)
4042 r_refdef.viewcache.maxentities = numentities;
4043 if (r_refdef.viewcache.entityvisible)
4044 Mem_Free(r_refdef.viewcache.entityvisible);
4045 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4047 if (r_refdef.viewcache.world_numclusters != numclusters)
4049 r_refdef.viewcache.world_numclusters = numclusters;
4050 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4051 if (r_refdef.viewcache.world_pvsbits)
4052 Mem_Free(r_refdef.viewcache.world_pvsbits);
4053 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4055 if (r_refdef.viewcache.world_numleafs != numleafs)
4057 r_refdef.viewcache.world_numleafs = numleafs;
4058 if (r_refdef.viewcache.world_leafvisible)
4059 Mem_Free(r_refdef.viewcache.world_leafvisible);
4060 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4062 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4064 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4065 if (r_refdef.viewcache.world_surfacevisible)
4066 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4067 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4071 extern rtexture_t *loadingscreentexture;
4072 static void gl_main_start(void)
4074 loadingscreentexture = NULL;
4075 r_texture_blanknormalmap = NULL;
4076 r_texture_white = NULL;
4077 r_texture_grey128 = NULL;
4078 r_texture_black = NULL;
4079 r_texture_whitecube = NULL;
4080 r_texture_normalizationcube = NULL;
4081 r_texture_fogattenuation = NULL;
4082 r_texture_fogheighttexture = NULL;
4083 r_texture_gammaramps = NULL;
4084 r_texture_numcubemaps = 0;
4085 r_uniformbufferalignment = 32;
4087 r_loaddds = r_texture_dds_load.integer != 0;
4088 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4090 switch(vid.renderpath)
4092 case RENDERPATH_GL20:
4093 case RENDERPATH_D3D9:
4094 case RENDERPATH_D3D10:
4095 case RENDERPATH_D3D11:
4096 case RENDERPATH_SOFT:
4097 case RENDERPATH_GLES2:
4098 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4099 Cvar_SetValueQuick(&gl_combine, 1);
4100 Cvar_SetValueQuick(&r_glsl, 1);
4101 r_loadnormalmap = true;
4104 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4105 if (vid.support.arb_uniform_buffer_object)
4106 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4109 case RENDERPATH_GL13:
4110 case RENDERPATH_GLES1:
4111 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4112 Cvar_SetValueQuick(&gl_combine, 1);
4113 Cvar_SetValueQuick(&r_glsl, 0);
4114 r_loadnormalmap = false;
4115 r_loadgloss = false;
4118 case RENDERPATH_GL11:
4119 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4120 Cvar_SetValueQuick(&gl_combine, 0);
4121 Cvar_SetValueQuick(&r_glsl, 0);
4122 r_loadnormalmap = false;
4123 r_loadgloss = false;
4129 R_FrameData_Reset();
4130 R_BufferData_Reset();
4134 memset(r_queries, 0, sizeof(r_queries));
4136 r_qwskincache = NULL;
4137 r_qwskincache_size = 0;
4139 // due to caching of texture_t references, the collision cache must be reset
4140 Collision_Cache_Reset(true);
4142 // set up r_skinframe loading system for textures
4143 memset(&r_skinframe, 0, sizeof(r_skinframe));
4144 r_skinframe.loadsequence = 1;
4145 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4147 r_main_texturepool = R_AllocTexturePool();
4148 R_BuildBlankTextures();
4150 if (vid.support.arb_texture_cube_map)
4153 R_BuildNormalizationCube();
4155 r_texture_fogattenuation = NULL;
4156 r_texture_fogheighttexture = NULL;
4157 r_texture_gammaramps = NULL;
4158 //r_texture_fogintensity = NULL;
4159 memset(&r_fb, 0, sizeof(r_fb));
4160 r_glsl_permutation = NULL;
4161 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4162 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4164 r_hlsl_permutation = NULL;
4165 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4166 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4168 memset(&r_svbsp, 0, sizeof (r_svbsp));
4170 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4171 r_texture_numcubemaps = 0;
4173 r_refdef.fogmasktable_density = 0;
4176 // For Steelstorm Android
4177 // FIXME CACHE the program and reload
4178 // FIXME see possible combinations for SS:BR android
4179 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4180 R_SetupShader_SetPermutationGLSL(0, 12);
4181 R_SetupShader_SetPermutationGLSL(0, 13);
4182 R_SetupShader_SetPermutationGLSL(0, 8388621);
4183 R_SetupShader_SetPermutationGLSL(3, 0);
4184 R_SetupShader_SetPermutationGLSL(3, 2048);
4185 R_SetupShader_SetPermutationGLSL(5, 0);
4186 R_SetupShader_SetPermutationGLSL(5, 2);
4187 R_SetupShader_SetPermutationGLSL(5, 2048);
4188 R_SetupShader_SetPermutationGLSL(5, 8388608);
4189 R_SetupShader_SetPermutationGLSL(11, 1);
4190 R_SetupShader_SetPermutationGLSL(11, 2049);
4191 R_SetupShader_SetPermutationGLSL(11, 8193);
4192 R_SetupShader_SetPermutationGLSL(11, 10241);
4193 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4197 static void gl_main_shutdown(void)
4200 R_FrameData_Reset();
4201 R_BufferData_Reset();
4203 R_Main_FreeViewCache();
4205 switch(vid.renderpath)
4207 case RENDERPATH_GL11:
4208 case RENDERPATH_GL13:
4209 case RENDERPATH_GL20:
4210 case RENDERPATH_GLES1:
4211 case RENDERPATH_GLES2:
4212 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4214 qglDeleteQueriesARB(r_maxqueries, r_queries);
4217 case RENDERPATH_D3D9:
4218 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4220 case RENDERPATH_D3D10:
4221 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4223 case RENDERPATH_D3D11:
4224 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4226 case RENDERPATH_SOFT:
4232 memset(r_queries, 0, sizeof(r_queries));
4234 r_qwskincache = NULL;
4235 r_qwskincache_size = 0;
4237 // clear out the r_skinframe state
4238 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4239 memset(&r_skinframe, 0, sizeof(r_skinframe));
4242 Mem_Free(r_svbsp.nodes);
4243 memset(&r_svbsp, 0, sizeof (r_svbsp));
4244 R_FreeTexturePool(&r_main_texturepool);
4245 loadingscreentexture = NULL;
4246 r_texture_blanknormalmap = NULL;
4247 r_texture_white = NULL;
4248 r_texture_grey128 = NULL;
4249 r_texture_black = NULL;
4250 r_texture_whitecube = NULL;
4251 r_texture_normalizationcube = NULL;
4252 r_texture_fogattenuation = NULL;
4253 r_texture_fogheighttexture = NULL;
4254 r_texture_gammaramps = NULL;
4255 r_texture_numcubemaps = 0;
4256 //r_texture_fogintensity = NULL;
4257 memset(&r_fb, 0, sizeof(r_fb));
4260 r_glsl_permutation = NULL;
4261 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4262 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4264 r_hlsl_permutation = NULL;
4265 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4266 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4270 static void gl_main_newmap(void)
4272 // FIXME: move this code to client
4273 char *entities, entname[MAX_QPATH];
4275 Mem_Free(r_qwskincache);
4276 r_qwskincache = NULL;
4277 r_qwskincache_size = 0;
4280 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4281 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4283 CL_ParseEntityLump(entities);
4287 if (cl.worldmodel->brush.entities)
4288 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4290 R_Main_FreeViewCache();
4292 R_FrameData_Reset();
4293 R_BufferData_Reset();
4296 void GL_Main_Init(void)
4299 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4300 R_InitShaderModeInfo();
4302 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4303 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4304 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4305 if (gamemode == GAME_NEHAHRA)
4307 Cvar_RegisterVariable (&gl_fogenable);
4308 Cvar_RegisterVariable (&gl_fogdensity);
4309 Cvar_RegisterVariable (&gl_fogred);
4310 Cvar_RegisterVariable (&gl_foggreen);
4311 Cvar_RegisterVariable (&gl_fogblue);
4312 Cvar_RegisterVariable (&gl_fogstart);
4313 Cvar_RegisterVariable (&gl_fogend);
4314 Cvar_RegisterVariable (&gl_skyclip);
4316 Cvar_RegisterVariable(&r_motionblur);
4317 Cvar_RegisterVariable(&r_damageblur);
4318 Cvar_RegisterVariable(&r_motionblur_averaging);
4319 Cvar_RegisterVariable(&r_motionblur_randomize);
4320 Cvar_RegisterVariable(&r_motionblur_minblur);
4321 Cvar_RegisterVariable(&r_motionblur_maxblur);
4322 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4323 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4324 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4325 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4326 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4327 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4328 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4329 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4330 Cvar_RegisterVariable(&r_equalize_entities_by);
4331 Cvar_RegisterVariable(&r_equalize_entities_to);
4332 Cvar_RegisterVariable(&r_depthfirst);
4333 Cvar_RegisterVariable(&r_useinfinitefarclip);
4334 Cvar_RegisterVariable(&r_farclip_base);
4335 Cvar_RegisterVariable(&r_farclip_world);
4336 Cvar_RegisterVariable(&r_nearclip);
4337 Cvar_RegisterVariable(&r_deformvertexes);
4338 Cvar_RegisterVariable(&r_transparent);
4339 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4340 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4341 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4342 Cvar_RegisterVariable(&r_showoverdraw);
4343 Cvar_RegisterVariable(&r_showbboxes);
4344 Cvar_RegisterVariable(&r_showbboxes_client);
4345 Cvar_RegisterVariable(&r_showsurfaces);
4346 Cvar_RegisterVariable(&r_showtris);
4347 Cvar_RegisterVariable(&r_shownormals);
4348 Cvar_RegisterVariable(&r_showlighting);
4349 Cvar_RegisterVariable(&r_showshadowvolumes);
4350 Cvar_RegisterVariable(&r_showcollisionbrushes);
4351 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4352 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4353 Cvar_RegisterVariable(&r_showdisabledepthtest);
4354 Cvar_RegisterVariable(&r_drawportals);
4355 Cvar_RegisterVariable(&r_drawentities);
4356 Cvar_RegisterVariable(&r_draw2d);
4357 Cvar_RegisterVariable(&r_drawworld);
4358 Cvar_RegisterVariable(&r_cullentities_trace);
4359 Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4360 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4361 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4362 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4363 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4364 Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4365 Cvar_RegisterVariable(&r_sortentities);
4366 Cvar_RegisterVariable(&r_drawviewmodel);
4367 Cvar_RegisterVariable(&r_drawexteriormodel);
4368 Cvar_RegisterVariable(&r_speeds);
4369 Cvar_RegisterVariable(&r_fullbrights);
4370 Cvar_RegisterVariable(&r_wateralpha);
4371 Cvar_RegisterVariable(&r_dynamic);
4372 Cvar_RegisterVariable(&r_fakelight);
4373 Cvar_RegisterVariable(&r_fakelight_intensity);
4374 Cvar_RegisterVariable(&r_fullbright);
4375 Cvar_RegisterVariable(&r_shadows);
4376 Cvar_RegisterVariable(&r_shadows_darken);
4377 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4378 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4379 Cvar_RegisterVariable(&r_shadows_throwdistance);
4380 Cvar_RegisterVariable(&r_shadows_throwdirection);
4381 Cvar_RegisterVariable(&r_shadows_focus);
4382 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4383 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4384 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4385 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4386 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4387 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4388 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4389 Cvar_RegisterVariable(&r_fog_exp2);
4390 Cvar_RegisterVariable(&r_fog_clear);
4391 Cvar_RegisterVariable(&r_drawfog);
4392 Cvar_RegisterVariable(&r_transparentdepthmasking);
4393 Cvar_RegisterVariable(&r_transparent_sortmindist);
4394 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4395 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4396 Cvar_RegisterVariable(&r_texture_dds_load);
4397 Cvar_RegisterVariable(&r_texture_dds_save);
4398 Cvar_RegisterVariable(&r_textureunits);
4399 Cvar_RegisterVariable(&gl_combine);
4400 Cvar_RegisterVariable(&r_usedepthtextures);
4401 Cvar_RegisterVariable(&r_viewfbo);
4402 Cvar_RegisterVariable(&r_viewscale);
4403 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4404 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4405 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4406 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4407 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4408 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4409 Cvar_RegisterVariable(&r_glsl);
4410 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4411 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4412 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4413 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4414 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4415 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4416 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4417 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4418 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4419 Cvar_RegisterVariable(&r_glsl_postprocess);
4420 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4421 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4422 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4423 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4424 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4425 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4426 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4427 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4428 Cvar_RegisterVariable(&r_celshading);
4429 Cvar_RegisterVariable(&r_celoutlines);
4431 Cvar_RegisterVariable(&r_water);
4432 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4433 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4434 Cvar_RegisterVariable(&r_water_clippingplanebias);
4435 Cvar_RegisterVariable(&r_water_refractdistort);
4436 Cvar_RegisterVariable(&r_water_reflectdistort);
4437 Cvar_RegisterVariable(&r_water_scissormode);
4438 Cvar_RegisterVariable(&r_water_lowquality);
4439 Cvar_RegisterVariable(&r_water_hideplayer);
4440 Cvar_RegisterVariable(&r_water_fbo);
4442 Cvar_RegisterVariable(&r_lerpsprites);
4443 Cvar_RegisterVariable(&r_lerpmodels);
4444 Cvar_RegisterVariable(&r_lerplightstyles);
4445 Cvar_RegisterVariable(&r_waterscroll);
4446 Cvar_RegisterVariable(&r_bloom);
4447 Cvar_RegisterVariable(&r_bloom_colorscale);
4448 Cvar_RegisterVariable(&r_bloom_brighten);
4449 Cvar_RegisterVariable(&r_bloom_blur);
4450 Cvar_RegisterVariable(&r_bloom_resolution);
4451 Cvar_RegisterVariable(&r_bloom_colorexponent);
4452 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4453 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4454 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4455 Cvar_RegisterVariable(&r_hdr_glowintensity);
4456 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4457 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4458 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4459 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4460 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4461 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4462 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4463 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4464 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4465 Cvar_RegisterVariable(&developer_texturelogging);
4466 Cvar_RegisterVariable(&gl_lightmaps);
4467 Cvar_RegisterVariable(&r_test);
4468 Cvar_RegisterVariable(&r_batch_multidraw);
4469 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4470 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4471 Cvar_RegisterVariable(&r_glsl_skeletal);
4472 Cvar_RegisterVariable(&r_glsl_saturation);
4473 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4474 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4475 Cvar_RegisterVariable(&r_framedatasize);
4476 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4477 Cvar_RegisterVariable(&r_buffermegs[i]);
4478 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4479 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4480 Cvar_SetValue("r_fullbrights", 0);
4481 #ifdef DP_MOBILETOUCH
4482 // GLES devices have terrible depth precision in general, so...
4483 Cvar_SetValueQuick(&r_nearclip, 4);
4484 Cvar_SetValueQuick(&r_farclip_base, 4096);
4485 Cvar_SetValueQuick(&r_farclip_world, 0);
4486 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4488 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4491 void Render_Init(void)
4504 R_LightningBeams_Init();
4514 extern char *ENGINE_EXTENSIONS;
4517 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4518 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4519 gl_version = (const char *)qglGetString(GL_VERSION);
4520 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4524 if (!gl_platformextensions)
4525 gl_platformextensions = "";
4527 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4528 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4529 Con_Printf("GL_VERSION: %s\n", gl_version);
4530 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4531 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4533 VID_CheckExtensions();
4535 // LordHavoc: report supported extensions
4537 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4539 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4542 // clear to black (loading plaque will be seen over this)
4543 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4547 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4551 if (r_trippy.integer)
4553 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4555 p = r_refdef.view.frustum + i;
4560 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4564 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4568 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4572 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4576 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4580 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4584 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4588 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4596 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4600 if (r_trippy.integer)
4602 for (i = 0;i < numplanes;i++)
4609 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4613 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4617 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4621 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4625 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4629 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4633 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4637 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4645 //==================================================================================
4647 // LordHavoc: this stores temporary data used within the same frame
4649 typedef struct r_framedata_mem_s
4651 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4652 size_t size; // how much usable space
4653 size_t current; // how much space in use
4654 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4655 size_t wantedsize; // how much space was allocated
4656 unsigned char *data; // start of real data (16byte aligned)
4660 static r_framedata_mem_t *r_framedata_mem;
4662 void R_FrameData_Reset(void)
4664 while (r_framedata_mem)
4666 r_framedata_mem_t *next = r_framedata_mem->purge;
4667 Mem_Free(r_framedata_mem);
4668 r_framedata_mem = next;
4672 static void R_FrameData_Resize(qboolean mustgrow)
4675 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4676 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4677 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4679 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4680 newmem->wantedsize = wantedsize;
4681 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4682 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4683 newmem->current = 0;
4685 newmem->purge = r_framedata_mem;
4686 r_framedata_mem = newmem;
4690 void R_FrameData_NewFrame(void)
4692 R_FrameData_Resize(false);
4693 if (!r_framedata_mem)
4695 // if we ran out of space on the last frame, free the old memory now
4696 while (r_framedata_mem->purge)
4698 // repeatedly remove the second item in the list, leaving only head
4699 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4700 Mem_Free(r_framedata_mem->purge);
4701 r_framedata_mem->purge = next;
4703 // reset the current mem pointer
4704 r_framedata_mem->current = 0;
4705 r_framedata_mem->mark = 0;
4708 void *R_FrameData_Alloc(size_t size)
4713 // align to 16 byte boundary - the data pointer is already aligned, so we
4714 // only need to ensure the size of every allocation is also aligned
4715 size = (size + 15) & ~15;
4717 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4719 // emergency - we ran out of space, allocate more memory
4720 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4721 newvalue = r_framedatasize.value * 2.0f;
4722 // 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
4723 if (sizeof(size_t) >= 8)
4724 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4726 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4727 // this might not be a growing it, but we'll allocate another buffer every time
4728 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4729 R_FrameData_Resize(true);
4732 data = r_framedata_mem->data + r_framedata_mem->current;
4733 r_framedata_mem->current += size;
4735 // count the usage for stats
4736 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4737 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4739 return (void *)data;
4742 void *R_FrameData_Store(size_t size, void *data)
4744 void *d = R_FrameData_Alloc(size);
4746 memcpy(d, data, size);
4750 void R_FrameData_SetMark(void)
4752 if (!r_framedata_mem)
4754 r_framedata_mem->mark = r_framedata_mem->current;
4757 void R_FrameData_ReturnToMark(void)
4759 if (!r_framedata_mem)
4761 r_framedata_mem->current = r_framedata_mem->mark;
4764 //==================================================================================
4766 // avoid reusing the same buffer objects on consecutive frames
4767 #define R_BUFFERDATA_CYCLE 3
4769 typedef struct r_bufferdata_buffer_s
4771 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4772 size_t size; // how much usable space
4773 size_t current; // how much space in use
4774 r_meshbuffer_t *buffer; // the buffer itself
4776 r_bufferdata_buffer_t;
4778 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4779 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4781 /// frees all dynamic buffers
4782 void R_BufferData_Reset(void)
4785 r_bufferdata_buffer_t **p, *mem;
4786 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4788 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4791 p = &r_bufferdata_buffer[cycle][type];
4797 R_Mesh_DestroyMeshBuffer(mem->buffer);
4804 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4805 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4807 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4809 float newvalue = r_buffermegs[type].value;
4811 // increase the cvar if we have to (but only if we already have a mem)
4812 if (mustgrow && mem)
4814 newvalue = bound(0.25f, newvalue, 256.0f);
4815 while (newvalue * 1024*1024 < minsize)
4818 // clamp the cvar to valid range
4819 newvalue = bound(0.25f, newvalue, 256.0f);
4820 if (r_buffermegs[type].value != newvalue)
4821 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4823 // calculate size in bytes
4824 size = (size_t)(newvalue * 1024*1024);
4825 size = bound(131072, size, 256*1024*1024);
4827 // allocate a new buffer if the size is different (purge old one later)
4828 // or if we were told we must grow the buffer
4829 if (!mem || mem->size != size || mustgrow)
4831 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4834 if (type == R_BUFFERDATA_VERTEX)
4835 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4836 else if (type == R_BUFFERDATA_INDEX16)
4837 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4838 else if (type == R_BUFFERDATA_INDEX32)
4839 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4840 else if (type == R_BUFFERDATA_UNIFORM)
4841 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4842 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4843 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4847 void R_BufferData_NewFrame(void)
4850 r_bufferdata_buffer_t **p, *mem;
4851 // cycle to the next frame's buffers
4852 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4853 // if we ran out of space on the last time we used these buffers, free the old memory now
4854 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4856 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4858 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4859 // free all but the head buffer, this is how we recycle obsolete
4860 // buffers after they are no longer in use
4861 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4867 R_Mesh_DestroyMeshBuffer(mem->buffer);
4870 // reset the current offset
4871 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4876 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4878 r_bufferdata_buffer_t *mem;
4882 *returnbufferoffset = 0;
4884 // align size to a byte boundary appropriate for the buffer type, this
4885 // makes all allocations have aligned start offsets
4886 if (type == R_BUFFERDATA_UNIFORM)
4887 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4889 padsize = (datasize + 15) & ~15;
4891 // if we ran out of space in this buffer we must allocate a new one
4892 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)
4893 R_BufferData_Resize(type, true, padsize);
4895 // if the resize did not give us enough memory, fail
4896 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)
4897 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4899 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4900 offset = (int)mem->current;
4901 mem->current += padsize;
4903 // upload the data to the buffer at the chosen offset
4905 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4906 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4908 // count the usage for stats
4909 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4910 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4912 // return the buffer offset
4913 *returnbufferoffset = offset;
4918 //==================================================================================
4920 // LordHavoc: animcache originally written by Echon, rewritten since then
4923 * Animation cache prevents re-generating mesh data for an animated model
4924 * multiple times in one frame for lighting, shadowing, reflections, etc.
4927 void R_AnimCache_Free(void)
4931 void R_AnimCache_ClearCache(void)
4934 entity_render_t *ent;
4936 for (i = 0;i < r_refdef.scene.numentities;i++)
4938 ent = r_refdef.scene.entities[i];
4939 ent->animcache_vertex3f = NULL;
4940 ent->animcache_vertex3f_vertexbuffer = NULL;
4941 ent->animcache_vertex3f_bufferoffset = 0;
4942 ent->animcache_normal3f = NULL;
4943 ent->animcache_normal3f_vertexbuffer = NULL;
4944 ent->animcache_normal3f_bufferoffset = 0;
4945 ent->animcache_svector3f = NULL;
4946 ent->animcache_svector3f_vertexbuffer = NULL;
4947 ent->animcache_svector3f_bufferoffset = 0;
4948 ent->animcache_tvector3f = NULL;
4949 ent->animcache_tvector3f_vertexbuffer = NULL;
4950 ent->animcache_tvector3f_bufferoffset = 0;
4951 ent->animcache_vertexmesh = NULL;
4952 ent->animcache_vertexmesh_vertexbuffer = NULL;
4953 ent->animcache_vertexmesh_bufferoffset = 0;
4954 ent->animcache_skeletaltransform3x4 = NULL;
4955 ent->animcache_skeletaltransform3x4buffer = NULL;
4956 ent->animcache_skeletaltransform3x4offset = 0;
4957 ent->animcache_skeletaltransform3x4size = 0;
4961 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4965 // check if we need the meshbuffers
4966 if (!vid.useinterleavedarrays)
4969 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4970 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4971 // TODO: upload vertexbuffer?
4972 if (ent->animcache_vertexmesh)
4974 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4975 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4976 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4977 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4978 for (i = 0;i < numvertices;i++)
4979 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4980 if (ent->animcache_svector3f)
4981 for (i = 0;i < numvertices;i++)
4982 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4983 if (ent->animcache_tvector3f)
4984 for (i = 0;i < numvertices;i++)
4985 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4986 if (ent->animcache_normal3f)
4987 for (i = 0;i < numvertices;i++)
4988 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4992 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4994 dp_model_t *model = ent->model;
4997 // see if this ent is worth caching
4998 if (!model || !model->Draw || !model->AnimateVertices)
5000 // nothing to cache if it contains no animations and has no skeleton
5001 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
5003 // see if it is already cached for gpuskeletal
5004 if (ent->animcache_skeletaltransform3x4)
5006 // see if it is already cached as a mesh
5007 if (ent->animcache_vertex3f)
5009 // check if we need to add normals or tangents
5010 if (ent->animcache_normal3f)
5011 wantnormals = false;
5012 if (ent->animcache_svector3f)
5013 wanttangents = false;
5014 if (!wantnormals && !wanttangents)
5018 // check which kind of cache we need to generate
5019 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5021 // cache the skeleton so the vertex shader can use it
5022 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5023 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5024 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5025 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5026 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
5027 // note: this can fail if the buffer is at the grow limit
5028 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5029 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5031 else if (ent->animcache_vertex3f)
5033 // mesh was already cached but we may need to add normals/tangents
5034 // (this only happens with multiple views, reflections, cameras, etc)
5035 if (wantnormals || wanttangents)
5037 numvertices = model->surfmesh.num_vertices;
5039 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5042 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5043 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5045 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5046 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5047 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5048 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5049 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5054 // generate mesh cache
5055 numvertices = model->surfmesh.num_vertices;
5056 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5058 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5061 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5062 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5064 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5065 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5066 if (wantnormals || wanttangents)
5068 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5069 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5070 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5072 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5073 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5074 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5079 void R_AnimCache_CacheVisibleEntities(void)
5082 qboolean wantnormals = true;
5083 qboolean wanttangents = !r_showsurfaces.integer;
5085 switch(vid.renderpath)
5087 case RENDERPATH_GL20:
5088 case RENDERPATH_D3D9:
5089 case RENDERPATH_D3D10:
5090 case RENDERPATH_D3D11:
5091 case RENDERPATH_GLES2:
5093 case RENDERPATH_GL11:
5094 case RENDERPATH_GL13:
5095 case RENDERPATH_GLES1:
5096 wanttangents = false;
5098 case RENDERPATH_SOFT:
5102 if (r_shownormals.integer)
5103 wanttangents = wantnormals = true;
5105 // TODO: thread this
5106 // NOTE: R_PrepareRTLights() also caches entities
5108 for (i = 0;i < r_refdef.scene.numentities;i++)
5109 if (r_refdef.viewcache.entityvisible[i])
5110 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5113 //==================================================================================
5115 extern cvar_t r_overheadsprites_pushback;
5117 static void R_View_UpdateEntityLighting (void)
5120 entity_render_t *ent;
5121 vec3_t tempdiffusenormal, avg;
5122 vec_t f, fa, fd, fdd;
5123 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5125 for (i = 0;i < r_refdef.scene.numentities;i++)
5127 ent = r_refdef.scene.entities[i];
5129 // skip unseen models
5130 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5134 if (ent->model && ent->model == cl.worldmodel)
5136 // TODO: use modellight for r_ambient settings on world?
5137 VectorSet(ent->modellight_ambient, 0, 0, 0);
5138 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5139 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5143 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5145 // aleady updated by CSQC
5146 // TODO: force modellight on BSP models in this case?
5147 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5151 // fetch the lighting from the worldmodel data
5152 VectorClear(ent->modellight_ambient);
5153 VectorClear(ent->modellight_diffuse);
5154 VectorClear(tempdiffusenormal);
5155 if (ent->flags & RENDER_LIGHT)
5158 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5160 // complete lightning for lit sprites
5161 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5162 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5164 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5165 org[2] = org[2] + r_overheadsprites_pushback.value;
5166 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5169 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5171 if(ent->flags & RENDER_EQUALIZE)
5173 // first fix up ambient lighting...
5174 if(r_equalize_entities_minambient.value > 0)
5176 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5179 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5180 if(fa < r_equalize_entities_minambient.value * fd)
5183 // fa'/fd' = minambient
5184 // fa'+0.25*fd' = fa+0.25*fd
5186 // fa' = fd' * minambient
5187 // fd'*(0.25+minambient) = fa+0.25*fd
5189 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5190 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5192 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5193 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
5194 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5195 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5200 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5202 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5203 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5207 // adjust brightness and saturation to target
5208 avg[0] = avg[1] = avg[2] = fa / f;
5209 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5210 avg[0] = avg[1] = avg[2] = fd / f;
5211 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5217 VectorSet(ent->modellight_ambient, 1, 1, 1);
5220 // move the light direction into modelspace coordinates for lighting code
5221 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5222 if(VectorLength2(ent->modellight_lightdir) == 0)
5223 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5224 VectorNormalize(ent->modellight_lightdir);
5228 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5231 vec3_t eyemins, eyemaxs;
5232 vec3_t boxmins, boxmaxs;
5235 dp_model_t *model = r_refdef.scene.worldmodel;
5236 static vec3_t positions[] = {
5237 { 0.5f, 0.5f, 0.5f },
5238 { 0.0f, 0.0f, 0.0f },
5239 { 0.0f, 0.0f, 1.0f },
5240 { 0.0f, 1.0f, 0.0f },
5241 { 0.0f, 1.0f, 1.0f },
5242 { 1.0f, 0.0f, 0.0f },
5243 { 1.0f, 0.0f, 1.0f },
5244 { 1.0f, 1.0f, 0.0f },
5245 { 1.0f, 1.0f, 1.0f },
5248 // sample count can be set to -1 to skip this logic, for flicker-prone objects
5252 // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5253 if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5256 if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5259 // expand the eye box a little
5260 eyemins[0] = eye[0] - eyejitter;
5261 eyemaxs[0] = eye[0] + eyejitter;
5262 eyemins[1] = eye[1] - eyejitter;
5263 eyemaxs[1] = eye[1] + eyejitter;
5264 eyemins[2] = eye[2] - eyejitter;
5265 eyemaxs[2] = eye[2] + eyejitter;
5266 // expand the box a little
5267 boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5268 boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5269 boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5270 boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5271 boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5272 boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5274 // return true if eye overlaps enlarged box
5275 if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5278 // try specific positions in the box first - note that these can be cached
5279 if (r_cullentities_trace_entityocclusion.integer)
5281 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5283 VectorCopy(eye, start);
5284 end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5285 end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5286 end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5287 //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5288 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5289 // not picky - if the trace ended anywhere in the box we're good
5290 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5294 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5297 // try various random positions
5298 for (i = 0; i < numsamples; i++)
5300 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5301 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5302 if (r_cullentities_trace_entityocclusion.integer)
5304 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5305 // not picky - if the trace ended anywhere in the box we're good
5306 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5309 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5317 static void R_View_UpdateEntityVisible (void)
5322 entity_render_t *ent;
5324 if (r_refdef.envmap || r_fb.water.hideplayer)
5325 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5326 else if (chase_active.integer || r_fb.water.renderingscene)
5327 renderimask = RENDER_VIEWMODEL;
5329 renderimask = RENDER_EXTERIORMODEL;
5330 if (!r_drawviewmodel.integer)
5331 renderimask |= RENDER_VIEWMODEL;
5332 if (!r_drawexteriormodel.integer)
5333 renderimask |= RENDER_EXTERIORMODEL;
5334 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5335 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5337 // worldmodel can check visibility
5338 for (i = 0;i < r_refdef.scene.numentities;i++)
5340 ent = r_refdef.scene.entities[i];
5341 if (!(ent->flags & renderimask))
5342 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)))
5343 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))
5344 r_refdef.viewcache.entityvisible[i] = true;
5349 // no worldmodel or it can't check visibility
5350 for (i = 0;i < r_refdef.scene.numentities;i++)
5352 ent = r_refdef.scene.entities[i];
5353 if (!(ent->flags & renderimask))
5354 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)))
5355 r_refdef.viewcache.entityvisible[i] = true;
5358 if (r_cullentities_trace.integer)
5360 for (i = 0;i < r_refdef.scene.numentities;i++)
5362 if (!r_refdef.viewcache.entityvisible[i])
5364 ent = r_refdef.scene.entities[i];
5365 if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5367 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5368 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5369 ent->last_trace_visibility = realtime;
5370 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5371 r_refdef.viewcache.entityvisible[i] = 0;
5377 /// only used if skyrendermasked, and normally returns false
5378 static int R_DrawBrushModelsSky (void)
5381 entity_render_t *ent;
5384 for (i = 0;i < r_refdef.scene.numentities;i++)
5386 if (!r_refdef.viewcache.entityvisible[i])
5388 ent = r_refdef.scene.entities[i];
5389 if (!ent->model || !ent->model->DrawSky)
5391 ent->model->DrawSky(ent);
5397 static void R_DrawNoModel(entity_render_t *ent);
5398 static void R_DrawModels(void)
5401 entity_render_t *ent;
5403 for (i = 0;i < r_refdef.scene.numentities;i++)
5405 if (!r_refdef.viewcache.entityvisible[i])
5407 ent = r_refdef.scene.entities[i];
5408 r_refdef.stats[r_stat_entities]++;
5410 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5413 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5414 Con_Printf("R_DrawModels\n");
5415 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]);
5416 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);
5417 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);
5420 if (ent->model && ent->model->Draw != NULL)
5421 ent->model->Draw(ent);
5427 static void R_DrawModelsDepth(void)
5430 entity_render_t *ent;
5432 for (i = 0;i < r_refdef.scene.numentities;i++)
5434 if (!r_refdef.viewcache.entityvisible[i])
5436 ent = r_refdef.scene.entities[i];
5437 if (ent->model && ent->model->DrawDepth != NULL)
5438 ent->model->DrawDepth(ent);
5442 static void R_DrawModelsDebug(void)
5445 entity_render_t *ent;
5447 for (i = 0;i < r_refdef.scene.numentities;i++)
5449 if (!r_refdef.viewcache.entityvisible[i])
5451 ent = r_refdef.scene.entities[i];
5452 if (ent->model && ent->model->DrawDebug != NULL)
5453 ent->model->DrawDebug(ent);
5457 static void R_DrawModelsAddWaterPlanes(void)
5460 entity_render_t *ent;
5462 for (i = 0;i < r_refdef.scene.numentities;i++)
5464 if (!r_refdef.viewcache.entityvisible[i])
5466 ent = r_refdef.scene.entities[i];
5467 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5468 ent->model->DrawAddWaterPlanes(ent);
5472 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}};
5474 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5476 if (r_hdr_irisadaptation.integer)
5481 vec3_t diffusenormal;
5483 vec_t brightness = 0.0f;
5488 VectorCopy(r_refdef.view.forward, forward);
5489 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5491 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5492 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5493 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5494 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5495 d = DotProduct(forward, diffusenormal);
5496 brightness += VectorLength(ambient);
5498 brightness += d * VectorLength(diffuse);
5500 brightness *= 1.0f / c;
5501 brightness += 0.00001f; // make sure it's never zero
5502 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5503 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5504 current = r_hdr_irisadaptation_value.value;
5506 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5507 else if (current > goal)
5508 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5509 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5510 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5512 else if (r_hdr_irisadaptation_value.value != 1.0f)
5513 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5516 static void R_View_SetFrustum(const int *scissor)
5519 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5520 vec3_t forward, left, up, origin, v;
5524 // flipped x coordinates (because x points left here)
5525 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5526 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5528 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5529 switch(vid.renderpath)
5531 case RENDERPATH_D3D9:
5532 case RENDERPATH_D3D10:
5533 case RENDERPATH_D3D11:
5534 // non-flipped y coordinates
5535 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5536 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5538 case RENDERPATH_SOFT:
5539 case RENDERPATH_GL11:
5540 case RENDERPATH_GL13:
5541 case RENDERPATH_GL20:
5542 case RENDERPATH_GLES1:
5543 case RENDERPATH_GLES2:
5544 // non-flipped y coordinates
5545 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5546 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5551 // we can't trust r_refdef.view.forward and friends in reflected scenes
5552 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5555 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5556 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5557 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5558 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5559 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5560 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5561 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5562 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5563 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5564 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5565 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5566 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5570 zNear = r_refdef.nearclip;
5571 nudge = 1.0 - 1.0 / (1<<23);
5572 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5573 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5574 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5575 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5576 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5577 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5578 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5579 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5585 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5586 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5587 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5588 r_refdef.view.frustum[0].dist = m[15] - m[12];
5590 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5591 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5592 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5593 r_refdef.view.frustum[1].dist = m[15] + m[12];
5595 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5596 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5597 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5598 r_refdef.view.frustum[2].dist = m[15] - m[13];
5600 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5601 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5602 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5603 r_refdef.view.frustum[3].dist = m[15] + m[13];
5605 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5606 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5607 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5608 r_refdef.view.frustum[4].dist = m[15] - m[14];
5610 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5611 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5612 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5613 r_refdef.view.frustum[5].dist = m[15] + m[14];
5616 if (r_refdef.view.useperspective)
5618 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5619 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]);
5620 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]);
5621 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]);
5622 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]);
5624 // then the normals from the corners relative to origin
5625 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5626 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5627 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5628 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5630 // in a NORMAL view, forward cross left == up
5631 // in a REFLECTED view, forward cross left == down
5632 // so our cross products above need to be adjusted for a left handed coordinate system
5633 CrossProduct(forward, left, v);
5634 if(DotProduct(v, up) < 0)
5636 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5637 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5638 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5639 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5642 // Leaving those out was a mistake, those were in the old code, and they
5643 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5644 // I couldn't reproduce it after adding those normalizations. --blub
5645 VectorNormalize(r_refdef.view.frustum[0].normal);
5646 VectorNormalize(r_refdef.view.frustum[1].normal);
5647 VectorNormalize(r_refdef.view.frustum[2].normal);
5648 VectorNormalize(r_refdef.view.frustum[3].normal);
5650 // make the corners absolute
5651 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5652 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5653 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5654 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5657 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5659 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5660 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5661 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5662 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5663 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5667 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5668 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5669 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5670 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5671 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5672 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5673 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5674 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5675 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5676 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5678 r_refdef.view.numfrustumplanes = 5;
5680 if (r_refdef.view.useclipplane)
5682 r_refdef.view.numfrustumplanes = 6;
5683 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5686 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5687 PlaneClassify(r_refdef.view.frustum + i);
5689 // LordHavoc: note to all quake engine coders, Quake had a special case
5690 // for 90 degrees which assumed a square view (wrong), so I removed it,
5691 // Quake2 has it disabled as well.
5693 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5694 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5695 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5696 //PlaneClassify(&frustum[0]);
5698 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5699 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5700 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5701 //PlaneClassify(&frustum[1]);
5703 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5704 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5705 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5706 //PlaneClassify(&frustum[2]);
5708 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5709 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5710 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5711 //PlaneClassify(&frustum[3]);
5714 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5715 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5716 //PlaneClassify(&frustum[4]);
5719 static void R_View_UpdateWithScissor(const int *myscissor)
5721 R_Main_ResizeViewCache();
5722 R_View_SetFrustum(myscissor);
5723 R_View_WorldVisibility(r_refdef.view.useclipplane);
5724 R_View_UpdateEntityVisible();
5725 R_View_UpdateEntityLighting();
5728 static void R_View_Update(void)
5730 R_Main_ResizeViewCache();
5731 R_View_SetFrustum(NULL);
5732 R_View_WorldVisibility(r_refdef.view.useclipplane);
5733 R_View_UpdateEntityVisible();
5734 R_View_UpdateEntityLighting();
5737 float viewscalefpsadjusted = 1.0f;
5739 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5741 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5742 scale = bound(0.03125f, scale, 1.0f);
5743 *outwidth = (int)ceil(width * scale);
5744 *outheight = (int)ceil(height * scale);
5747 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5749 const float *customclipplane = NULL;
5751 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5752 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5754 // LordHavoc: couldn't figure out how to make this approach the
5755 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5756 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5757 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5758 dist = r_refdef.view.clipplane.dist;
5759 plane[0] = r_refdef.view.clipplane.normal[0];
5760 plane[1] = r_refdef.view.clipplane.normal[1];
5761 plane[2] = r_refdef.view.clipplane.normal[2];
5763 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5766 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5767 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5769 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5770 if (!r_refdef.view.useperspective)
5771 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);
5772 else if (vid.stencil && r_useinfinitefarclip.integer)
5773 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);
5775 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);
5776 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5777 R_SetViewport(&r_refdef.view.viewport);
5778 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5780 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5781 float screenplane[4];
5782 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5783 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5784 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5785 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5786 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5790 void R_EntityMatrix(const matrix4x4_t *matrix)
5792 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5794 gl_modelmatrixchanged = false;
5795 gl_modelmatrix = *matrix;
5796 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5797 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5798 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5799 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5801 switch(vid.renderpath)
5803 case RENDERPATH_D3D9:
5805 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5806 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5809 case RENDERPATH_D3D10:
5810 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5812 case RENDERPATH_D3D11:
5813 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5815 case RENDERPATH_GL11:
5816 case RENDERPATH_GL13:
5817 case RENDERPATH_GLES1:
5819 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5822 case RENDERPATH_SOFT:
5823 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5824 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5826 case RENDERPATH_GL20:
5827 case RENDERPATH_GLES2:
5828 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5829 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5835 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5837 r_viewport_t viewport;
5841 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5842 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);
5843 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5844 R_SetViewport(&viewport);
5845 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5846 GL_Color(1, 1, 1, 1);
5847 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5848 GL_BlendFunc(GL_ONE, GL_ZERO);
5849 GL_ScissorTest(false);
5850 GL_DepthMask(false);
5851 GL_DepthRange(0, 1);
5852 GL_DepthTest(false);
5853 GL_DepthFunc(GL_LEQUAL);
5854 R_EntityMatrix(&identitymatrix);
5855 R_Mesh_ResetTextureState();
5856 GL_PolygonOffset(0, 0);
5857 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5858 switch(vid.renderpath)
5860 case RENDERPATH_GL11:
5861 case RENDERPATH_GL13:
5862 case RENDERPATH_GL20:
5863 case RENDERPATH_GLES1:
5864 case RENDERPATH_GLES2:
5865 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5867 case RENDERPATH_D3D9:
5868 case RENDERPATH_D3D10:
5869 case RENDERPATH_D3D11:
5870 case RENDERPATH_SOFT:
5873 GL_CullFace(GL_NONE);
5878 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5882 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5885 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5889 R_SetupView(true, fbo, depthtexture, colortexture);
5890 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5891 GL_Color(1, 1, 1, 1);
5892 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5893 GL_BlendFunc(GL_ONE, GL_ZERO);
5894 GL_ScissorTest(true);
5896 GL_DepthRange(0, 1);
5898 GL_DepthFunc(GL_LEQUAL);
5899 R_EntityMatrix(&identitymatrix);
5900 R_Mesh_ResetTextureState();
5901 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5902 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5903 switch(vid.renderpath)
5905 case RENDERPATH_GL11:
5906 case RENDERPATH_GL13:
5907 case RENDERPATH_GL20:
5908 case RENDERPATH_GLES1:
5909 case RENDERPATH_GLES2:
5910 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5912 case RENDERPATH_D3D9:
5913 case RENDERPATH_D3D10:
5914 case RENDERPATH_D3D11:
5915 case RENDERPATH_SOFT:
5918 GL_CullFace(r_refdef.view.cullface_back);
5923 R_RenderView_UpdateViewVectors
5926 void R_RenderView_UpdateViewVectors(void)
5928 // break apart the view matrix into vectors for various purposes
5929 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5930 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5931 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5932 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5933 // make an inverted copy of the view matrix for tracking sprites
5934 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5937 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5938 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5940 static void R_Water_StartFrame(void)
5943 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5944 r_waterstate_waterplane_t *p;
5945 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;
5947 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5950 switch(vid.renderpath)
5952 case RENDERPATH_GL20:
5953 case RENDERPATH_D3D9:
5954 case RENDERPATH_D3D10:
5955 case RENDERPATH_D3D11:
5956 case RENDERPATH_SOFT:
5957 case RENDERPATH_GLES2:
5959 case RENDERPATH_GL11:
5960 case RENDERPATH_GL13:
5961 case RENDERPATH_GLES1:
5965 // set waterwidth and waterheight to the water resolution that will be
5966 // used (often less than the screen resolution for faster rendering)
5967 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5969 // calculate desired texture sizes
5970 // can't use water if the card does not support the texture size
5971 if (!r_water.integer || r_showsurfaces.integer)
5972 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5973 else if (vid.support.arb_texture_non_power_of_two)
5975 texturewidth = waterwidth;
5976 textureheight = waterheight;
5977 camerawidth = waterwidth;
5978 cameraheight = waterheight;
5982 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5983 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5984 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5985 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5988 // allocate textures as needed
5989 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))
5991 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5992 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5994 if (p->texture_refraction)
5995 R_FreeTexture(p->texture_refraction);
5996 p->texture_refraction = NULL;
5997 if (p->fbo_refraction)
5998 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5999 p->fbo_refraction = 0;
6000 if (p->texture_reflection)
6001 R_FreeTexture(p->texture_reflection);
6002 p->texture_reflection = NULL;
6003 if (p->fbo_reflection)
6004 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
6005 p->fbo_reflection = 0;
6006 if (p->texture_camera)
6007 R_FreeTexture(p->texture_camera);
6008 p->texture_camera = NULL;
6010 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
6013 memset(&r_fb.water, 0, sizeof(r_fb.water));
6014 r_fb.water.texturewidth = texturewidth;
6015 r_fb.water.textureheight = textureheight;
6016 r_fb.water.camerawidth = camerawidth;
6017 r_fb.water.cameraheight = cameraheight;
6020 if (r_fb.water.texturewidth)
6022 int scaledwidth, scaledheight;
6024 r_fb.water.enabled = true;
6026 // water resolution is usually reduced
6027 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6028 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6029 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
6031 // set up variables that will be used in shader setup
6032 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6033 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6034 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6035 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6038 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6039 r_fb.water.numwaterplanes = 0;
6042 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
6044 int planeindex, bestplaneindex, vertexindex;
6045 vec3_t mins, maxs, normal, center, v, n;
6046 vec_t planescore, bestplanescore;
6048 r_waterstate_waterplane_t *p;
6049 texture_t *t = R_GetCurrentTexture(surface->texture);
6051 rsurface.texture = t;
6052 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6053 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6054 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6056 // average the vertex normals, find the surface bounds (after deformvertexes)
6057 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6058 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6059 VectorCopy(n, normal);
6060 VectorCopy(v, mins);
6061 VectorCopy(v, maxs);
6062 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6064 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6065 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6066 VectorAdd(normal, n, normal);
6067 mins[0] = min(mins[0], v[0]);
6068 mins[1] = min(mins[1], v[1]);
6069 mins[2] = min(mins[2], v[2]);
6070 maxs[0] = max(maxs[0], v[0]);
6071 maxs[1] = max(maxs[1], v[1]);
6072 maxs[2] = max(maxs[2], v[2]);
6074 VectorNormalize(normal);
6075 VectorMAM(0.5f, mins, 0.5f, maxs, center);
6077 VectorCopy(normal, plane.normal);
6078 VectorNormalize(plane.normal);
6079 plane.dist = DotProduct(center, plane.normal);
6080 PlaneClassify(&plane);
6081 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6083 // skip backfaces (except if nocullface is set)
6084 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6086 VectorNegate(plane.normal, plane.normal);
6088 PlaneClassify(&plane);
6092 // find a matching plane if there is one
6093 bestplaneindex = -1;
6094 bestplanescore = 1048576.0f;
6095 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6097 if(p->camera_entity == t->camera_entity)
6099 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6100 if (bestplaneindex < 0 || bestplanescore > planescore)
6102 bestplaneindex = planeindex;
6103 bestplanescore = planescore;
6107 planeindex = bestplaneindex;
6109 // if this surface does not fit any known plane rendered this frame, add one
6110 if (planeindex < 0 || bestplanescore > 0.001f)
6112 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6114 // store the new plane
6115 planeindex = r_fb.water.numwaterplanes++;
6116 p = r_fb.water.waterplanes + planeindex;
6118 // clear materialflags and pvs
6119 p->materialflags = 0;
6120 p->pvsvalid = false;
6121 p->camera_entity = t->camera_entity;
6122 VectorCopy(mins, p->mins);
6123 VectorCopy(maxs, p->maxs);
6127 // We're totally screwed.
6133 // merge mins/maxs when we're adding this surface to the plane
6134 p = r_fb.water.waterplanes + planeindex;
6135 p->mins[0] = min(p->mins[0], mins[0]);
6136 p->mins[1] = min(p->mins[1], mins[1]);
6137 p->mins[2] = min(p->mins[2], mins[2]);
6138 p->maxs[0] = max(p->maxs[0], maxs[0]);
6139 p->maxs[1] = max(p->maxs[1], maxs[1]);
6140 p->maxs[2] = max(p->maxs[2], maxs[2]);
6142 // merge this surface's materialflags into the waterplane
6143 p->materialflags |= t->currentmaterialflags;
6144 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6146 // merge this surface's PVS into the waterplane
6147 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6148 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6150 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6156 extern cvar_t r_drawparticles;
6157 extern cvar_t r_drawdecals;
6159 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6162 r_refdef_view_t originalview;
6163 r_refdef_view_t myview;
6164 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;
6165 r_waterstate_waterplane_t *p;
6167 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;
6170 originalview = r_refdef.view;
6172 // lowquality hack, temporarily shut down some cvars and restore afterwards
6173 qualityreduction = r_water_lowquality.integer;
6174 if (qualityreduction > 0)
6176 if (qualityreduction >= 1)
6178 old_r_shadows = r_shadows.integer;
6179 old_r_worldrtlight = r_shadow_realtime_world.integer;
6180 old_r_dlight = r_shadow_realtime_dlight.integer;
6181 Cvar_SetValueQuick(&r_shadows, 0);
6182 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6183 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6185 if (qualityreduction >= 2)
6187 old_r_dynamic = r_dynamic.integer;
6188 old_r_particles = r_drawparticles.integer;
6189 old_r_decals = r_drawdecals.integer;
6190 Cvar_SetValueQuick(&r_dynamic, 0);
6191 Cvar_SetValueQuick(&r_drawparticles, 0);
6192 Cvar_SetValueQuick(&r_drawdecals, 0);
6196 // make sure enough textures are allocated
6197 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6199 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6201 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6203 if (!p->texture_refraction)
6204 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);
6205 if (!p->texture_refraction)
6209 if (r_fb.water.depthtexture == NULL)
6210 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6211 if (p->fbo_refraction == 0)
6212 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6215 else if (p->materialflags & MATERIALFLAG_CAMERA)
6217 if (!p->texture_camera)
6218 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);
6219 if (!p->texture_camera)
6223 if (r_fb.water.depthtexture == NULL)
6224 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6225 if (p->fbo_camera == 0)
6226 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6230 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6232 if (!p->texture_reflection)
6233 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);
6234 if (!p->texture_reflection)
6238 if (r_fb.water.depthtexture == NULL)
6239 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6240 if (p->fbo_reflection == 0)
6241 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6247 r_refdef.view = originalview;
6248 r_refdef.view.showdebug = false;
6249 r_refdef.view.width = r_fb.water.waterwidth;
6250 r_refdef.view.height = r_fb.water.waterheight;
6251 r_refdef.view.useclipplane = true;
6252 myview = r_refdef.view;
6253 r_fb.water.renderingscene = true;
6254 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6256 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6258 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6260 r_refdef.view = myview;
6261 if(r_water_scissormode.integer)
6263 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6264 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6265 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6268 // render reflected scene and copy into texture
6269 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6270 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6271 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6272 r_refdef.view.clipplane = p->plane;
6273 // reverse the cullface settings for this render
6274 r_refdef.view.cullface_front = GL_FRONT;
6275 r_refdef.view.cullface_back = GL_BACK;
6276 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6278 r_refdef.view.usecustompvs = true;
6280 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6282 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6285 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6286 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6287 R_ClearScreen(r_refdef.fogenabled);
6288 if(r_water_scissormode.integer & 2)
6289 R_View_UpdateWithScissor(myscissor);
6292 R_AnimCache_CacheVisibleEntities();
6293 if(r_water_scissormode.integer & 1)
6294 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6295 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6297 if (!p->fbo_reflection)
6298 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);
6299 r_fb.water.hideplayer = false;
6302 // render the normal view scene and copy into texture
6303 // (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)
6304 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6306 r_refdef.view = myview;
6307 if(r_water_scissormode.integer)
6309 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6310 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6311 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6314 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6316 r_refdef.view.clipplane = p->plane;
6317 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6318 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6320 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6322 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6323 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6324 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6325 R_RenderView_UpdateViewVectors();
6326 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6328 r_refdef.view.usecustompvs = true;
6329 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);
6333 PlaneClassify(&r_refdef.view.clipplane);
6335 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6336 R_ClearScreen(r_refdef.fogenabled);
6337 if(r_water_scissormode.integer & 2)
6338 R_View_UpdateWithScissor(myscissor);
6341 R_AnimCache_CacheVisibleEntities();
6342 if(r_water_scissormode.integer & 1)
6343 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6344 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6346 if (!p->fbo_refraction)
6347 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);
6348 r_fb.water.hideplayer = false;
6350 else if (p->materialflags & MATERIALFLAG_CAMERA)
6352 r_refdef.view = myview;
6354 r_refdef.view.clipplane = p->plane;
6355 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6356 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6358 r_refdef.view.width = r_fb.water.camerawidth;
6359 r_refdef.view.height = r_fb.water.cameraheight;
6360 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6361 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6362 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6363 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6365 if(p->camera_entity)
6367 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6368 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6371 // note: all of the view is used for displaying... so
6372 // there is no use in scissoring
6374 // reverse the cullface settings for this render
6375 r_refdef.view.cullface_front = GL_FRONT;
6376 r_refdef.view.cullface_back = GL_BACK;
6377 // also reverse the view matrix
6378 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
6379 R_RenderView_UpdateViewVectors();
6380 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6382 r_refdef.view.usecustompvs = true;
6383 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);
6386 // camera needs no clipplane
6387 r_refdef.view.useclipplane = false;
6389 PlaneClassify(&r_refdef.view.clipplane);
6391 r_fb.water.hideplayer = false;
6393 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6394 R_ClearScreen(r_refdef.fogenabled);
6396 R_AnimCache_CacheVisibleEntities();
6397 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6400 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);
6401 r_fb.water.hideplayer = false;
6405 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6406 r_fb.water.renderingscene = false;
6407 r_refdef.view = originalview;
6408 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6409 if (!r_fb.water.depthtexture)
6410 R_ClearScreen(r_refdef.fogenabled);
6412 R_AnimCache_CacheVisibleEntities();
6415 r_refdef.view = originalview;
6416 r_fb.water.renderingscene = false;
6417 Cvar_SetValueQuick(&r_water, 0);
6418 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6420 // lowquality hack, restore cvars
6421 if (qualityreduction > 0)
6423 if (qualityreduction >= 1)
6425 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6426 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6427 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6429 if (qualityreduction >= 2)
6431 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6432 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6433 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6438 static void R_Bloom_StartFrame(void)
6441 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6442 int viewwidth, viewheight;
6443 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6444 textype_t textype = TEXTYPE_COLORBUFFER;
6446 switch (vid.renderpath)
6448 case RENDERPATH_GL20:
6449 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6450 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6452 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6453 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6456 case RENDERPATH_GL11:
6457 case RENDERPATH_GL13:
6458 case RENDERPATH_GLES1:
6459 case RENDERPATH_GLES2:
6460 case RENDERPATH_D3D9:
6461 case RENDERPATH_D3D10:
6462 case RENDERPATH_D3D11:
6463 r_fb.usedepthtextures = false;
6465 case RENDERPATH_SOFT:
6466 r_fb.usedepthtextures = true;
6470 if (r_viewscale_fpsscaling.integer)
6472 double actualframetime;
6473 double targetframetime;
6475 actualframetime = r_refdef.lastdrawscreentime;
6476 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6477 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6478 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6479 if (r_viewscale_fpsscaling_stepsize.value > 0)
6480 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6481 viewscalefpsadjusted += adjust;
6482 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6485 viewscalefpsadjusted = 1.0f;
6487 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6489 switch(vid.renderpath)
6491 case RENDERPATH_GL20:
6492 case RENDERPATH_D3D9:
6493 case RENDERPATH_D3D10:
6494 case RENDERPATH_D3D11:
6495 case RENDERPATH_SOFT:
6496 case RENDERPATH_GLES2:
6498 case RENDERPATH_GL11:
6499 case RENDERPATH_GL13:
6500 case RENDERPATH_GLES1:
6504 // set bloomwidth and bloomheight to the bloom resolution that will be
6505 // used (often less than the screen resolution for faster rendering)
6506 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6507 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6508 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6509 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6510 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6512 // calculate desired texture sizes
6513 if (vid.support.arb_texture_non_power_of_two)
6515 screentexturewidth = vid.width;
6516 screentextureheight = vid.height;
6517 bloomtexturewidth = r_fb.bloomwidth;
6518 bloomtextureheight = r_fb.bloomheight;
6522 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6523 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6524 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6525 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6528 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))
6530 Cvar_SetValueQuick(&r_bloom, 0);
6531 Cvar_SetValueQuick(&r_motionblur, 0);
6532 Cvar_SetValueQuick(&r_damageblur, 0);
6535 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6537 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6539 && r_viewscale.value == 1.0f
6540 && !r_viewscale_fpsscaling.integer)
6541 screentexturewidth = screentextureheight = 0;
6542 if (!r_bloom.integer)
6543 bloomtexturewidth = bloomtextureheight = 0;
6545 // allocate textures as needed
6546 if (r_fb.screentexturewidth != screentexturewidth
6547 || r_fb.screentextureheight != screentextureheight
6548 || r_fb.bloomtexturewidth != bloomtexturewidth
6549 || r_fb.bloomtextureheight != bloomtextureheight
6550 || r_fb.textype != textype
6551 || useviewfbo != (r_fb.fbo != 0))
6553 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6555 if (r_fb.bloomtexture[i])
6556 R_FreeTexture(r_fb.bloomtexture[i]);
6557 r_fb.bloomtexture[i] = NULL;
6559 if (r_fb.bloomfbo[i])
6560 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6561 r_fb.bloomfbo[i] = 0;
6565 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6568 if (r_fb.colortexture)
6569 R_FreeTexture(r_fb.colortexture);
6570 r_fb.colortexture = NULL;
6572 if (r_fb.depthtexture)
6573 R_FreeTexture(r_fb.depthtexture);
6574 r_fb.depthtexture = NULL;
6576 if (r_fb.ghosttexture)
6577 R_FreeTexture(r_fb.ghosttexture);
6578 r_fb.ghosttexture = NULL;
6580 r_fb.screentexturewidth = screentexturewidth;
6581 r_fb.screentextureheight = screentextureheight;
6582 r_fb.bloomtexturewidth = bloomtexturewidth;
6583 r_fb.bloomtextureheight = bloomtextureheight;
6584 r_fb.textype = textype;
6586 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6588 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6589 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);
6590 r_fb.ghosttexture_valid = false;
6591 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);
6594 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6595 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6596 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6600 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6602 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6604 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);
6606 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6611 // bloom texture is a different resolution
6612 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6613 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6614 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6615 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6616 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6618 // set up a texcoord array for the full resolution screen image
6619 // (we have to keep this around to copy back during final render)
6620 r_fb.screentexcoord2f[0] = 0;
6621 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6622 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6623 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6624 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6625 r_fb.screentexcoord2f[5] = 0;
6626 r_fb.screentexcoord2f[6] = 0;
6627 r_fb.screentexcoord2f[7] = 0;
6631 for (i = 1;i < 8;i += 2)
6633 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6637 // set up a texcoord array for the reduced resolution bloom image
6638 // (which will be additive blended over the screen image)
6639 r_fb.bloomtexcoord2f[0] = 0;
6640 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6641 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6642 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6643 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6644 r_fb.bloomtexcoord2f[5] = 0;
6645 r_fb.bloomtexcoord2f[6] = 0;
6646 r_fb.bloomtexcoord2f[7] = 0;
6648 switch(vid.renderpath)
6650 case RENDERPATH_GL11:
6651 case RENDERPATH_GL13:
6652 case RENDERPATH_GL20:
6653 case RENDERPATH_SOFT:
6654 case RENDERPATH_GLES1:
6655 case RENDERPATH_GLES2:
6657 case RENDERPATH_D3D9:
6658 case RENDERPATH_D3D10:
6659 case RENDERPATH_D3D11:
6660 for (i = 0;i < 4;i++)
6662 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6663 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6664 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6665 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6670 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6673 r_refdef.view.clear = true;
6676 static void R_Bloom_MakeTexture(void)
6679 float xoffset, yoffset, r, brighten;
6681 float colorscale = r_bloom_colorscale.value;
6683 r_refdef.stats[r_stat_bloom]++;
6686 // this copy is unnecessary since it happens in R_BlendView already
6689 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);
6690 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6694 // scale down screen texture to the bloom texture size
6696 r_fb.bloomindex = 0;
6697 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6698 R_SetViewport(&r_fb.bloomviewport);
6699 GL_CullFace(GL_NONE);
6700 GL_DepthTest(false);
6701 GL_BlendFunc(GL_ONE, GL_ZERO);
6702 GL_Color(colorscale, colorscale, colorscale, 1);
6703 // 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...
6704 switch(vid.renderpath)
6706 case RENDERPATH_GL11:
6707 case RENDERPATH_GL13:
6708 case RENDERPATH_GL20:
6709 case RENDERPATH_GLES1:
6710 case RENDERPATH_GLES2:
6711 case RENDERPATH_SOFT:
6712 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6714 case RENDERPATH_D3D9:
6715 case RENDERPATH_D3D10:
6716 case RENDERPATH_D3D11:
6717 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6720 // TODO: do boxfilter scale-down in shader?
6721 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6722 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6723 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6725 // we now have a properly scaled bloom image
6726 if (!r_fb.bloomfbo[r_fb.bloomindex])
6728 // copy it into the bloom texture
6729 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);
6730 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6733 // multiply bloom image by itself as many times as desired
6734 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6736 intex = r_fb.bloomtexture[r_fb.bloomindex];
6737 r_fb.bloomindex ^= 1;
6738 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6740 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6741 if (!r_fb.bloomfbo[r_fb.bloomindex])
6743 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6744 GL_Color(r,r,r,1); // apply fix factor
6749 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6750 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6751 GL_Color(1,1,1,1); // no fix factor supported here
6753 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6754 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6755 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6756 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6758 if (!r_fb.bloomfbo[r_fb.bloomindex])
6760 // copy the darkened image to a texture
6761 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);
6762 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6766 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6767 brighten = r_bloom_brighten.value;
6768 brighten = sqrt(brighten);
6770 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6772 for (dir = 0;dir < 2;dir++)
6774 intex = r_fb.bloomtexture[r_fb.bloomindex];
6775 r_fb.bloomindex ^= 1;
6776 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6777 // blend on at multiple vertical offsets to achieve a vertical blur
6778 // TODO: do offset blends using GLSL
6779 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6780 GL_BlendFunc(GL_ONE, GL_ZERO);
6781 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6782 for (x = -range;x <= range;x++)
6784 if (!dir){xoffset = 0;yoffset = x;}
6785 else {xoffset = x;yoffset = 0;}
6786 xoffset /= (float)r_fb.bloomtexturewidth;
6787 yoffset /= (float)r_fb.bloomtextureheight;
6788 // compute a texcoord array with the specified x and y offset
6789 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6790 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6791 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6792 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6793 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6794 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6795 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6796 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6797 // this r value looks like a 'dot' particle, fading sharply to
6798 // black at the edges
6799 // (probably not realistic but looks good enough)
6800 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6801 //r = brighten/(range*2+1);
6802 r = brighten / (range * 2 + 1);
6804 r *= (1 - x*x/(float)(range*range));
6805 GL_Color(r, r, r, 1);
6806 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6807 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6808 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6809 GL_BlendFunc(GL_ONE, GL_ONE);
6812 if (!r_fb.bloomfbo[r_fb.bloomindex])
6814 // copy the vertically or horizontally blurred bloom view to a texture
6815 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);
6816 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6821 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6823 dpuint64 permutation;
6824 float uservecs[4][4];
6826 R_EntityMatrix(&identitymatrix);
6828 switch (vid.renderpath)
6830 case RENDERPATH_GL20:
6831 case RENDERPATH_D3D9:
6832 case RENDERPATH_D3D10:
6833 case RENDERPATH_D3D11:
6834 case RENDERPATH_SOFT:
6835 case RENDERPATH_GLES2:
6837 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6838 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6839 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6840 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6841 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6843 if (r_fb.colortexture)
6847 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);
6848 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6851 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6853 // declare variables
6854 float blur_factor, blur_mouseaccel, blur_velocity;
6855 static float blur_average;
6856 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6858 // set a goal for the factoring
6859 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6860 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6861 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6862 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6863 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6864 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6866 // from the goal, pick an averaged value between goal and last value
6867 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6868 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6870 // enforce minimum amount of blur
6871 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6873 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6875 // calculate values into a standard alpha
6876 cl.motionbluralpha = 1 - exp(-
6878 (r_motionblur.value * blur_factor / 80)
6880 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6883 max(0.0001, cl.time - cl.oldtime) // fps independent
6886 // randomization for the blur value to combat persistent ghosting
6887 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6888 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6891 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6892 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6894 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6895 GL_Color(1, 1, 1, cl.motionbluralpha);
6896 switch(vid.renderpath)
6898 case RENDERPATH_GL11:
6899 case RENDERPATH_GL13:
6900 case RENDERPATH_GL20:
6901 case RENDERPATH_GLES1:
6902 case RENDERPATH_GLES2:
6903 case RENDERPATH_SOFT:
6904 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6906 case RENDERPATH_D3D9:
6907 case RENDERPATH_D3D10:
6908 case RENDERPATH_D3D11:
6909 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6912 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6913 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6914 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6917 // updates old view angles for next pass
6918 VectorCopy(cl.viewangles, blur_oldangles);
6920 // copy view into the ghost texture
6921 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);
6922 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6923 r_fb.ghosttexture_valid = true;
6928 // no r_fb.colortexture means we're rendering to the real fb
6929 // we may still have to do view tint...
6930 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6932 // apply a color tint to the whole view
6933 R_ResetViewRendering2D(0, NULL, NULL);
6934 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6935 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6936 R_SetupShader_Generic_NoTexture(false, true);
6937 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6938 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6940 break; // no screen processing, no bloom, skip it
6943 if (r_fb.bloomtexture[0])
6945 // make the bloom texture
6946 R_Bloom_MakeTexture();
6949 #if _MSC_VER >= 1400
6950 #define sscanf sscanf_s
6952 memset(uservecs, 0, sizeof(uservecs));
6953 if (r_glsl_postprocess_uservec1_enable.integer)
6954 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6955 if (r_glsl_postprocess_uservec2_enable.integer)
6956 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6957 if (r_glsl_postprocess_uservec3_enable.integer)
6958 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6959 if (r_glsl_postprocess_uservec4_enable.integer)
6960 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6962 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6963 GL_Color(1, 1, 1, 1);
6964 GL_BlendFunc(GL_ONE, GL_ZERO);
6966 switch(vid.renderpath)
6968 case RENDERPATH_GL20:
6969 case RENDERPATH_GLES2:
6970 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6971 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6972 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6973 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6974 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6975 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]);
6976 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6977 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]);
6978 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]);
6979 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]);
6980 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]);
6981 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6982 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6983 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);
6985 case RENDERPATH_D3D9:
6987 // 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...
6988 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6989 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6990 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6991 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6992 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6993 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6994 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6995 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6996 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6997 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6998 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6999 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
7000 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7001 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7004 case RENDERPATH_D3D10:
7005 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7007 case RENDERPATH_D3D11:
7008 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7010 case RENDERPATH_SOFT:
7011 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7012 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
7013 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
7014 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
7015 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7016 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7017 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7018 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7019 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7020 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7021 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7022 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
7023 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7024 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7029 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7030 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
7032 case RENDERPATH_GL11:
7033 case RENDERPATH_GL13:
7034 case RENDERPATH_GLES1:
7035 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7037 // apply a color tint to the whole view
7038 R_ResetViewRendering2D(0, NULL, NULL);
7039 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7040 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
7041 R_SetupShader_Generic_NoTexture(false, true);
7042 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7043 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7049 matrix4x4_t r_waterscrollmatrix;
7051 void R_UpdateFog(void)
7054 if (gamemode == GAME_NEHAHRA)
7056 if (gl_fogenable.integer)
7058 r_refdef.oldgl_fogenable = true;
7059 r_refdef.fog_density = gl_fogdensity.value;
7060 r_refdef.fog_red = gl_fogred.value;
7061 r_refdef.fog_green = gl_foggreen.value;
7062 r_refdef.fog_blue = gl_fogblue.value;
7063 r_refdef.fog_alpha = 1;
7064 r_refdef.fog_start = 0;
7065 r_refdef.fog_end = gl_skyclip.value;
7066 r_refdef.fog_height = 1<<30;
7067 r_refdef.fog_fadedepth = 128;
7069 else if (r_refdef.oldgl_fogenable)
7071 r_refdef.oldgl_fogenable = false;
7072 r_refdef.fog_density = 0;
7073 r_refdef.fog_red = 0;
7074 r_refdef.fog_green = 0;
7075 r_refdef.fog_blue = 0;
7076 r_refdef.fog_alpha = 0;
7077 r_refdef.fog_start = 0;
7078 r_refdef.fog_end = 0;
7079 r_refdef.fog_height = 1<<30;
7080 r_refdef.fog_fadedepth = 128;
7085 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7086 r_refdef.fog_start = max(0, r_refdef.fog_start);
7087 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7089 if (r_refdef.fog_density && r_drawfog.integer)
7091 r_refdef.fogenabled = true;
7092 // this is the point where the fog reaches 0.9986 alpha, which we
7093 // consider a good enough cutoff point for the texture
7094 // (0.9986 * 256 == 255.6)
7095 if (r_fog_exp2.integer)
7096 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7098 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7099 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7100 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7101 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7102 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7103 R_BuildFogHeightTexture();
7104 // fog color was already set
7105 // update the fog texture
7106 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)
7107 R_BuildFogTexture();
7108 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7109 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7112 r_refdef.fogenabled = false;
7115 if (r_refdef.fog_density)
7117 r_refdef.fogcolor[0] = r_refdef.fog_red;
7118 r_refdef.fogcolor[1] = r_refdef.fog_green;
7119 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7121 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7122 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7123 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7124 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7128 VectorCopy(r_refdef.fogcolor, fogvec);
7129 // color.rgb *= ContrastBoost * SceneBrightness;
7130 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7131 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7132 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7133 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7138 void R_UpdateVariables(void)
7142 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7144 r_refdef.farclip = r_farclip_base.value;
7145 if (r_refdef.scene.worldmodel)
7146 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7147 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7149 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7150 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7151 r_refdef.polygonfactor = 0;
7152 r_refdef.polygonoffset = 0;
7153 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7154 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7156 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7157 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7158 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7159 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7160 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7161 if (FAKELIGHT_ENABLED)
7163 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7165 else if (r_refdef.scene.worldmodel)
7167 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7169 if (r_showsurfaces.integer)
7171 r_refdef.scene.rtworld = false;
7172 r_refdef.scene.rtworldshadows = false;
7173 r_refdef.scene.rtdlight = false;
7174 r_refdef.scene.rtdlightshadows = false;
7175 r_refdef.lightmapintensity = 0;
7178 r_gpuskeletal = false;
7179 switch(vid.renderpath)
7181 case RENDERPATH_GL20:
7182 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7183 case RENDERPATH_D3D9:
7184 case RENDERPATH_D3D10:
7185 case RENDERPATH_D3D11:
7186 case RENDERPATH_SOFT:
7187 case RENDERPATH_GLES2:
7188 if(v_glslgamma.integer && !vid_gammatables_trivial)
7190 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7192 // build GLSL gamma texture
7193 #define RAMPWIDTH 256
7194 unsigned short ramp[RAMPWIDTH * 3];
7195 unsigned char rampbgr[RAMPWIDTH][4];
7198 r_texture_gammaramps_serial = vid_gammatables_serial;
7200 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7201 for(i = 0; i < RAMPWIDTH; ++i)
7203 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7204 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7205 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7208 if (r_texture_gammaramps)
7210 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7214 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7220 // remove GLSL gamma texture
7223 case RENDERPATH_GL11:
7224 case RENDERPATH_GL13:
7225 case RENDERPATH_GLES1:
7230 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7231 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7237 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7238 if( scenetype != r_currentscenetype ) {
7239 // store the old scenetype
7240 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7241 r_currentscenetype = scenetype;
7242 // move in the new scene
7243 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7252 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7254 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7255 if( scenetype == r_currentscenetype ) {
7256 return &r_refdef.scene;
7258 return &r_scenes_store[ scenetype ];
7262 static int R_SortEntities_Compare(const void *ap, const void *bp)
7264 const entity_render_t *a = *(const entity_render_t **)ap;
7265 const entity_render_t *b = *(const entity_render_t **)bp;
7268 if(a->model < b->model)
7270 if(a->model > b->model)
7274 // TODO possibly calculate the REAL skinnum here first using
7276 if(a->skinnum < b->skinnum)
7278 if(a->skinnum > b->skinnum)
7281 // everything we compared is equal
7284 static void R_SortEntities(void)
7286 // below or equal 2 ents, sorting never gains anything
7287 if(r_refdef.scene.numentities <= 2)
7290 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7298 int dpsoftrast_test;
7299 extern cvar_t r_shadow_bouncegrid;
7300 void R_RenderView(void)
7302 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7304 rtexture_t *depthtexture;
7305 rtexture_t *colortexture;
7307 dpsoftrast_test = r_test.integer;
7309 if (r_timereport_active)
7310 R_TimeReport("start");
7311 r_textureframe++; // used only by R_GetCurrentTexture
7312 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7314 if(R_CompileShader_CheckStaticParms())
7317 if (!r_drawentities.integer)
7318 r_refdef.scene.numentities = 0;
7319 else if (r_sortentities.integer)
7322 R_AnimCache_ClearCache();
7324 /* adjust for stereo display */
7325 if(R_Stereo_Active())
7327 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);
7328 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7331 if (r_refdef.view.isoverlay)
7333 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7334 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7335 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7336 R_TimeReport("depthclear");
7338 r_refdef.view.showdebug = false;
7340 r_fb.water.enabled = false;
7341 r_fb.water.numwaterplanes = 0;
7343 R_RenderScene(0, NULL, NULL);
7345 r_refdef.view.matrix = originalmatrix;
7351 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7353 r_refdef.view.matrix = originalmatrix;
7357 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7359 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7360 // in sRGB fallback, behave similar to true sRGB: convert this
7361 // value from linear to sRGB
7362 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7364 R_RenderView_UpdateViewVectors();
7366 R_Shadow_UpdateWorldLightSelection();
7368 R_Bloom_StartFrame();
7370 // apply bloom brightness offset
7371 if(r_fb.bloomtexture[0])
7372 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7374 R_Water_StartFrame();
7376 // now we probably have an fbo to render into
7378 depthtexture = r_fb.depthtexture;
7379 colortexture = r_fb.colortexture;
7382 if (r_timereport_active)
7383 R_TimeReport("viewsetup");
7385 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7387 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7389 R_ClearScreen(r_refdef.fogenabled);
7390 if (r_timereport_active)
7391 R_TimeReport("viewclear");
7393 r_refdef.view.clear = true;
7395 r_refdef.view.showdebug = true;
7398 if (r_timereport_active)
7399 R_TimeReport("visibility");
7401 R_AnimCache_CacheVisibleEntities();
7402 if (r_timereport_active)
7403 R_TimeReport("animcache");
7405 R_Shadow_UpdateBounceGridTexture();
7406 if (r_timereport_active && r_shadow_bouncegrid.integer)
7407 R_TimeReport("bouncegrid");
7409 r_fb.water.numwaterplanes = 0;
7410 if (r_fb.water.enabled)
7411 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7413 R_RenderScene(fbo, depthtexture, colortexture);
7414 r_fb.water.numwaterplanes = 0;
7416 R_BlendView(fbo, depthtexture, colortexture);
7417 if (r_timereport_active)
7418 R_TimeReport("blendview");
7420 GL_Scissor(0, 0, vid.width, vid.height);
7421 GL_ScissorTest(false);
7423 r_refdef.view.matrix = originalmatrix;
7428 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7430 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7432 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7433 if (r_timereport_active)
7434 R_TimeReport("waterworld");
7437 // don't let sound skip if going slow
7438 if (r_refdef.scene.extraupdate)
7441 R_DrawModelsAddWaterPlanes();
7442 if (r_timereport_active)
7443 R_TimeReport("watermodels");
7445 if (r_fb.water.numwaterplanes)
7447 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7448 if (r_timereport_active)
7449 R_TimeReport("waterscenes");
7453 extern cvar_t cl_locs_show;
7454 static void R_DrawLocs(void);
7455 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7456 static void R_DrawModelDecals(void);
7457 extern cvar_t cl_decals_newsystem;
7458 extern qboolean r_shadow_usingdeferredprepass;
7459 extern int r_shadow_shadowmapatlas_modelshadows_size;
7460 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7462 qboolean shadowmapping = false;
7464 if (r_timereport_active)
7465 R_TimeReport("beginscene");
7467 r_refdef.stats[r_stat_renders]++;
7471 // don't let sound skip if going slow
7472 if (r_refdef.scene.extraupdate)
7475 R_MeshQueue_BeginScene();
7479 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);
7481 if (r_timereport_active)
7482 R_TimeReport("skystartframe");
7484 if (cl.csqc_vidvars.drawworld)
7486 // don't let sound skip if going slow
7487 if (r_refdef.scene.extraupdate)
7490 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7492 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7493 if (r_timereport_active)
7494 R_TimeReport("worldsky");
7497 if (R_DrawBrushModelsSky() && r_timereport_active)
7498 R_TimeReport("bmodelsky");
7500 if (skyrendermasked && skyrenderlater)
7502 // we have to force off the water clipping plane while rendering sky
7503 R_SetupView(false, fbo, depthtexture, colortexture);
7505 R_SetupView(true, fbo, depthtexture, colortexture);
7506 if (r_timereport_active)
7507 R_TimeReport("sky");
7511 R_Shadow_PrepareModelShadows();
7512 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7513 if (r_timereport_active)
7514 R_TimeReport("preparelights");
7516 // render all the shadowmaps that will be used for this view
7517 shadowmapping = R_Shadow_ShadowMappingEnabled();
7518 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7520 R_Shadow_DrawShadowMaps();
7521 if (r_timereport_active)
7522 R_TimeReport("shadowmaps");
7525 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7526 if (r_shadow_usingdeferredprepass)
7527 R_Shadow_DrawPrepass();
7529 // now we begin the forward pass of the view render
7530 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7532 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7533 if (r_timereport_active)
7534 R_TimeReport("worlddepth");
7536 if (r_depthfirst.integer >= 2)
7538 R_DrawModelsDepth();
7539 if (r_timereport_active)
7540 R_TimeReport("modeldepth");
7543 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7545 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7546 if (r_timereport_active)
7547 R_TimeReport("world");
7550 // don't let sound skip if going slow
7551 if (r_refdef.scene.extraupdate)
7555 if (r_timereport_active)
7556 R_TimeReport("models");
7558 // don't let sound skip if going slow
7559 if (r_refdef.scene.extraupdate)
7562 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7564 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7565 R_Shadow_DrawModelShadows();
7566 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7567 // don't let sound skip if going slow
7568 if (r_refdef.scene.extraupdate)
7572 if (!r_shadow_usingdeferredprepass)
7574 R_Shadow_DrawLights();
7575 if (r_timereport_active)
7576 R_TimeReport("rtlights");
7579 // don't let sound skip if going slow
7580 if (r_refdef.scene.extraupdate)
7583 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7585 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7586 R_Shadow_DrawModelShadows();
7587 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7588 // don't let sound skip if going slow
7589 if (r_refdef.scene.extraupdate)
7593 if (cl.csqc_vidvars.drawworld)
7595 if (cl_decals_newsystem.integer)
7597 R_DrawModelDecals();
7598 if (r_timereport_active)
7599 R_TimeReport("modeldecals");
7604 if (r_timereport_active)
7605 R_TimeReport("decals");
7609 if (r_timereport_active)
7610 R_TimeReport("particles");
7613 if (r_timereport_active)
7614 R_TimeReport("explosions");
7618 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7620 if (r_refdef.view.showdebug)
7622 if (cl_locs_show.integer)
7625 if (r_timereport_active)
7626 R_TimeReport("showlocs");
7629 if (r_drawportals.integer)
7632 if (r_timereport_active)
7633 R_TimeReport("portals");
7636 if (r_showbboxes_client.value > 0)
7638 R_DrawEntityBBoxes(CLVM_prog);
7639 if (r_timereport_active)
7640 R_TimeReport("clbboxes");
7642 if (r_showbboxes.value > 0)
7644 R_DrawEntityBBoxes(SVVM_prog);
7645 if (r_timereport_active)
7646 R_TimeReport("svbboxes");
7650 if (r_transparent.integer)
7652 R_MeshQueue_RenderTransparent();
7653 if (r_timereport_active)
7654 R_TimeReport("drawtrans");
7657 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))
7659 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7660 if (r_timereport_active)
7661 R_TimeReport("worlddebug");
7662 R_DrawModelsDebug();
7663 if (r_timereport_active)
7664 R_TimeReport("modeldebug");
7667 if (cl.csqc_vidvars.drawworld)
7669 R_Shadow_DrawCoronas();
7670 if (r_timereport_active)
7671 R_TimeReport("coronas");
7676 GL_DepthTest(false);
7677 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7678 GL_Color(1, 1, 1, 1);
7679 qglBegin(GL_POLYGON);
7680 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7681 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7682 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7683 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7685 qglBegin(GL_POLYGON);
7686 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]);
7687 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]);
7688 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]);
7689 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]);
7691 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7695 // don't let sound skip if going slow
7696 if (r_refdef.scene.extraupdate)
7700 static const unsigned short bboxelements[36] =
7710 #define BBOXEDGES 13
7711 static const float bboxedges[BBOXEDGES][6] =
7714 { 0, 0, 0, 1, 1, 1 },
7716 { 0, 0, 0, 0, 1, 0 },
7717 { 0, 0, 0, 1, 0, 0 },
7718 { 0, 1, 0, 1, 1, 0 },
7719 { 1, 0, 0, 1, 1, 0 },
7721 { 0, 0, 1, 0, 1, 1 },
7722 { 0, 0, 1, 1, 0, 1 },
7723 { 0, 1, 1, 1, 1, 1 },
7724 { 1, 0, 1, 1, 1, 1 },
7726 { 0, 0, 0, 0, 0, 1 },
7727 { 1, 0, 0, 1, 0, 1 },
7728 { 0, 1, 0, 0, 1, 1 },
7729 { 1, 1, 0, 1, 1, 1 },
7732 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7734 int numvertices = BBOXEDGES * 8;
7735 float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7736 int numtriangles = BBOXEDGES * 12;
7737 unsigned short elements[BBOXEDGES * 36];
7739 float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7741 RSurf_ActiveWorldEntity();
7743 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7744 GL_DepthMask(false);
7745 GL_DepthRange(0, 1);
7746 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7748 for (edge = 0; edge < BBOXEDGES; edge++)
7750 for (i = 0; i < 3; i++)
7752 edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7753 edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7755 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7756 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7757 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7758 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7759 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7760 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7761 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7762 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7763 for (i = 0; i < 36; i++)
7764 elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7766 R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7767 if (r_refdef.fogenabled)
7769 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7771 f1 = RSurf_FogVertex(v);
7773 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7774 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7775 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7778 R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7779 R_Mesh_ResetTextureState();
7780 R_SetupShader_Generic_NoTexture(false, false);
7781 R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7784 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7786 // hacky overloading of the parameters
7787 prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7790 prvm_edict_t *edict;
7792 GL_CullFace(GL_NONE);
7793 R_SetupShader_Generic_NoTexture(false, false);
7795 for (i = 0;i < numsurfaces;i++)
7797 edict = PRVM_EDICT_NUM(surfacelist[i]);
7798 switch ((int)PRVM_serveredictfloat(edict, solid))
7800 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7801 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7802 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7803 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7804 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7805 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7806 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7808 if (prog == CLVM_prog)
7809 color[3] *= r_showbboxes_client.value;
7811 color[3] *= r_showbboxes.value;
7812 color[3] = bound(0, color[3], 1);
7813 GL_DepthTest(!r_showdisabledepthtest.integer);
7814 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7818 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7821 prvm_edict_t *edict;
7827 for (i = 0; i < prog->num_edicts; i++)
7829 edict = PRVM_EDICT_NUM(i);
7830 if (edict->priv.server->free)
7832 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7833 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7835 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7837 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7838 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7842 static const int nomodelelement3i[24] =
7854 static const unsigned short nomodelelement3s[24] =
7866 static const float nomodelvertex3f[6*3] =
7876 static const float nomodelcolor4f[6*4] =
7878 0.0f, 0.0f, 0.5f, 1.0f,
7879 0.0f, 0.0f, 0.5f, 1.0f,
7880 0.0f, 0.5f, 0.0f, 1.0f,
7881 0.0f, 0.5f, 0.0f, 1.0f,
7882 0.5f, 0.0f, 0.0f, 1.0f,
7883 0.5f, 0.0f, 0.0f, 1.0f
7886 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7892 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);
7894 // this is only called once per entity so numsurfaces is always 1, and
7895 // surfacelist is always {0}, so this code does not handle batches
7897 if (rsurface.ent_flags & RENDER_ADDITIVE)
7899 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7900 GL_DepthMask(false);
7902 else if (rsurface.colormod[3] < 1)
7904 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7905 GL_DepthMask(false);
7909 GL_BlendFunc(GL_ONE, GL_ZERO);
7912 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7913 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7914 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7915 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7916 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7917 for (i = 0, c = color4f;i < 6;i++, c += 4)
7919 c[0] *= rsurface.colormod[0];
7920 c[1] *= rsurface.colormod[1];
7921 c[2] *= rsurface.colormod[2];
7922 c[3] *= rsurface.colormod[3];
7924 if (r_refdef.fogenabled)
7926 for (i = 0, c = color4f;i < 6;i++, c += 4)
7928 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7930 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7931 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7932 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7935 // R_Mesh_ResetTextureState();
7936 R_SetupShader_Generic_NoTexture(false, false);
7937 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7938 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7941 void R_DrawNoModel(entity_render_t *ent)
7944 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7945 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7946 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7948 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7951 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7953 vec3_t right1, right2, diff, normal;
7955 VectorSubtract (org2, org1, normal);
7957 // calculate 'right' vector for start
7958 VectorSubtract (r_refdef.view.origin, org1, diff);
7959 CrossProduct (normal, diff, right1);
7960 VectorNormalize (right1);
7962 // calculate 'right' vector for end
7963 VectorSubtract (r_refdef.view.origin, org2, diff);
7964 CrossProduct (normal, diff, right2);
7965 VectorNormalize (right2);
7967 vert[ 0] = org1[0] + width * right1[0];
7968 vert[ 1] = org1[1] + width * right1[1];
7969 vert[ 2] = org1[2] + width * right1[2];
7970 vert[ 3] = org1[0] - width * right1[0];
7971 vert[ 4] = org1[1] - width * right1[1];
7972 vert[ 5] = org1[2] - width * right1[2];
7973 vert[ 6] = org2[0] - width * right2[0];
7974 vert[ 7] = org2[1] - width * right2[1];
7975 vert[ 8] = org2[2] - width * right2[2];
7976 vert[ 9] = org2[0] + width * right2[0];
7977 vert[10] = org2[1] + width * right2[1];
7978 vert[11] = org2[2] + width * right2[2];
7981 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)
7983 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7984 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7985 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7986 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7987 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7988 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7989 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7990 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7991 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7992 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7993 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7994 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7997 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8002 VectorSet(v, x, y, z);
8003 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8004 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8006 if (i == mesh->numvertices)
8008 if (mesh->numvertices < mesh->maxvertices)
8010 VectorCopy(v, vertex3f);
8011 mesh->numvertices++;
8013 return mesh->numvertices;
8019 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8023 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8024 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8025 e = mesh->element3i + mesh->numtriangles * 3;
8026 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8028 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8029 if (mesh->numtriangles < mesh->maxtriangles)
8034 mesh->numtriangles++;
8036 element[1] = element[2];
8040 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8044 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8045 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8046 e = mesh->element3i + mesh->numtriangles * 3;
8047 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8049 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8050 if (mesh->numtriangles < mesh->maxtriangles)
8055 mesh->numtriangles++;
8057 element[1] = element[2];
8061 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8062 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8064 int planenum, planenum2;
8067 mplane_t *plane, *plane2;
8069 double temppoints[2][256*3];
8070 // figure out how large a bounding box we need to properly compute this brush
8072 for (w = 0;w < numplanes;w++)
8073 maxdist = max(maxdist, fabs(planes[w].dist));
8074 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8075 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8076 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8080 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8081 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8083 if (planenum2 == planenum)
8085 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);
8088 if (tempnumpoints < 3)
8090 // generate elements forming a triangle fan for this polygon
8091 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8095 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)
8097 texturelayer_t *layer;
8098 layer = t->currentlayers + t->currentnumlayers++;
8100 layer->depthmask = depthmask;
8101 layer->blendfunc1 = blendfunc1;
8102 layer->blendfunc2 = blendfunc2;
8103 layer->texture = texture;
8104 layer->texmatrix = *matrix;
8105 layer->color[0] = r;
8106 layer->color[1] = g;
8107 layer->color[2] = b;
8108 layer->color[3] = a;
8111 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8113 if(parms[0] == 0 && parms[1] == 0)
8115 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8116 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8121 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8124 index = parms[2] + rsurface.shadertime * parms[3];
8125 index -= floor(index);
8126 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8129 case Q3WAVEFUNC_NONE:
8130 case Q3WAVEFUNC_NOISE:
8131 case Q3WAVEFUNC_COUNT:
8134 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8135 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8136 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8137 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8138 case Q3WAVEFUNC_TRIANGLE:
8140 f = index - floor(index);
8153 f = parms[0] + parms[1] * f;
8154 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8155 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8159 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8166 matrix4x4_t matrix, temp;
8167 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8168 // it's better to have one huge fixup every 9 hours than gradual
8169 // degradation over time which looks consistently bad after many hours.
8171 // tcmod scroll in particular suffers from this degradation which can't be
8172 // effectively worked around even with floor() tricks because we don't
8173 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8174 // a workaround involving floor() would be incorrect anyway...
8175 shadertime = rsurface.shadertime;
8176 if (shadertime >= 32768.0f)
8177 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8178 switch(tcmod->tcmod)
8182 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8183 matrix = r_waterscrollmatrix;
8185 matrix = identitymatrix;
8187 case Q3TCMOD_ENTITYTRANSLATE:
8188 // this is used in Q3 to allow the gamecode to control texcoord
8189 // scrolling on the entity, which is not supported in darkplaces yet.
8190 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8192 case Q3TCMOD_ROTATE:
8193 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8194 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8195 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8198 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8200 case Q3TCMOD_SCROLL:
8201 // this particular tcmod is a "bug for bug" compatible one with regards to
8202 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8203 // specifically did the wrapping and so we must mimic that...
8204 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8205 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8206 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8208 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8209 w = (int) tcmod->parms[0];
8210 h = (int) tcmod->parms[1];
8211 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8213 idx = (int) floor(f * w * h);
8214 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8216 case Q3TCMOD_STRETCH:
8217 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8218 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8220 case Q3TCMOD_TRANSFORM:
8221 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8222 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8223 VectorSet(tcmat + 6, 0 , 0 , 1);
8224 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8225 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8227 case Q3TCMOD_TURBULENT:
8228 // this is handled in the RSurf_PrepareVertices function
8229 matrix = identitymatrix;
8233 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8236 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8238 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8239 char name[MAX_QPATH];
8240 skinframe_t *skinframe;
8241 unsigned char pixels[296*194];
8242 strlcpy(cache->name, skinname, sizeof(cache->name));
8243 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8244 if (developer_loading.integer)
8245 Con_Printf("loading %s\n", name);
8246 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8247 if (!skinframe || !skinframe->base)
8250 fs_offset_t filesize;
8252 f = FS_LoadFile(name, tempmempool, true, &filesize);
8255 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8256 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8260 cache->skinframe = skinframe;
8263 texture_t *R_GetCurrentTexture(texture_t *t)
8266 const entity_render_t *ent = rsurface.entity;
8267 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8268 q3shaderinfo_layer_tcmod_t *tcmod;
8270 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8271 return t->currentframe;
8272 t->update_lastrenderframe = r_textureframe;
8273 t->update_lastrenderentity = (void *)ent;
8275 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8276 t->camera_entity = ent->entitynumber;
8278 t->camera_entity = 0;
8280 // switch to an alternate material if this is a q1bsp animated material
8282 texture_t *texture = t;
8283 int s = rsurface.ent_skinnum;
8284 if ((unsigned int)s >= (unsigned int)model->numskins)
8286 if (model->skinscenes)
8288 if (model->skinscenes[s].framecount > 1)
8289 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8291 s = model->skinscenes[s].firstframe;
8294 t = t + s * model->num_surfaces;
8297 // use an alternate animation if the entity's frame is not 0,
8298 // and only if the texture has an alternate animation
8299 if (t->animated == 2) // q2bsp
8300 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8301 else if (rsurface.ent_alttextures && t->anim_total[1])
8302 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8304 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8306 texture->currentframe = t;
8309 // update currentskinframe to be a qw skin or animation frame
8310 if (rsurface.ent_qwskin >= 0)
8312 i = rsurface.ent_qwskin;
8313 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8315 r_qwskincache_size = cl.maxclients;
8317 Mem_Free(r_qwskincache);
8318 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8320 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8321 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8322 t->currentskinframe = r_qwskincache[i].skinframe;
8323 if (t->materialshaderpass && t->currentskinframe == NULL)
8324 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8326 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8327 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8328 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8329 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8331 t->currentmaterialflags = t->basematerialflags;
8332 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8333 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8334 t->currentalpha *= r_wateralpha.value;
8335 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8336 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8337 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8338 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8339 if (!(rsurface.ent_flags & RENDER_LIGHT))
8340 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8341 else if (FAKELIGHT_ENABLED)
8343 // no modellight if using fakelight for the map
8345 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8347 // pick a model lighting mode
8348 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8349 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8351 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8353 if (rsurface.ent_flags & RENDER_ADDITIVE)
8354 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8355 else if (t->currentalpha < 1)
8356 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8357 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8358 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8359 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8360 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8361 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8362 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8363 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8364 if (t->backgroundshaderpass)
8365 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8366 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8368 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8369 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8372 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8373 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8375 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8376 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8378 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8379 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8381 // there is no tcmod
8382 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8384 t->currenttexmatrix = r_waterscrollmatrix;
8385 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8387 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8389 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8390 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8393 if (t->materialshaderpass)
8394 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8395 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8397 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8398 if (t->currentskinframe->qpixels)
8399 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8400 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8401 if (!t->basetexture)
8402 t->basetexture = r_texture_notexture;
8403 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8404 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8405 t->nmaptexture = t->currentskinframe->nmap;
8406 if (!t->nmaptexture)
8407 t->nmaptexture = r_texture_blanknormalmap;
8408 t->glosstexture = r_texture_black;
8409 t->glowtexture = t->currentskinframe->glow;
8410 t->fogtexture = t->currentskinframe->fog;
8411 t->reflectmasktexture = t->currentskinframe->reflect;
8412 if (t->backgroundshaderpass)
8414 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8415 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8416 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8417 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8418 t->backgroundglosstexture = r_texture_black;
8419 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8420 if (!t->backgroundnmaptexture)
8421 t->backgroundnmaptexture = r_texture_blanknormalmap;
8422 // make sure that if glow is going to be used, both textures are not NULL
8423 if (!t->backgroundglowtexture && t->glowtexture)
8424 t->backgroundglowtexture = r_texture_black;
8425 if (!t->glowtexture && t->backgroundglowtexture)
8426 t->glowtexture = r_texture_black;
8430 t->backgroundbasetexture = r_texture_white;
8431 t->backgroundnmaptexture = r_texture_blanknormalmap;
8432 t->backgroundglosstexture = r_texture_black;
8433 t->backgroundglowtexture = NULL;
8435 t->specularpower = r_shadow_glossexponent.value;
8436 // TODO: store reference values for these in the texture?
8437 t->specularscale = 0;
8438 if (r_shadow_gloss.integer > 0)
8440 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8442 if (r_shadow_glossintensity.value > 0)
8444 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8445 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8446 t->specularscale = r_shadow_glossintensity.value;
8449 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8451 t->glosstexture = r_texture_white;
8452 t->backgroundglosstexture = r_texture_white;
8453 t->specularscale = r_shadow_gloss2intensity.value;
8454 t->specularpower = r_shadow_gloss2exponent.value;
8457 t->specularscale *= t->specularscalemod;
8458 t->specularpower *= t->specularpowermod;
8459 t->rtlightambient = 0;
8461 // lightmaps mode looks bad with dlights using actual texturing, so turn
8462 // off the colormap and glossmap, but leave the normalmap on as it still
8463 // accurately represents the shading involved
8464 if (gl_lightmaps.integer)
8466 t->basetexture = r_texture_grey128;
8467 t->pantstexture = r_texture_black;
8468 t->shirttexture = r_texture_black;
8469 if (gl_lightmaps.integer < 2)
8470 t->nmaptexture = r_texture_blanknormalmap;
8471 t->glosstexture = r_texture_black;
8472 t->glowtexture = NULL;
8473 t->fogtexture = NULL;
8474 t->reflectmasktexture = NULL;
8475 t->backgroundbasetexture = NULL;
8476 if (gl_lightmaps.integer < 2)
8477 t->backgroundnmaptexture = r_texture_blanknormalmap;
8478 t->backgroundglosstexture = r_texture_black;
8479 t->backgroundglowtexture = NULL;
8480 t->specularscale = 0;
8481 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8484 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8485 VectorClear(t->dlightcolor);
8486 t->currentnumlayers = 0;
8487 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8489 int blendfunc1, blendfunc2;
8491 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8493 blendfunc1 = GL_SRC_ALPHA;
8494 blendfunc2 = GL_ONE;
8496 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8498 blendfunc1 = GL_SRC_ALPHA;
8499 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8501 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8503 blendfunc1 = t->customblendfunc[0];
8504 blendfunc2 = t->customblendfunc[1];
8508 blendfunc1 = GL_ONE;
8509 blendfunc2 = GL_ZERO;
8511 // don't colormod evilblend textures
8512 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8513 VectorSet(t->lightmapcolor, 1, 1, 1);
8514 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8515 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8517 // fullbright is not affected by r_refdef.lightmapintensity
8518 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]);
8519 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8520 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]);
8521 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8522 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]);
8526 vec3_t ambientcolor;
8528 // set the color tint used for lights affecting this surface
8529 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8531 // q3bsp has no lightmap updates, so the lightstylevalue that
8532 // would normally be baked into the lightmap must be
8533 // applied to the color
8534 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8535 if (model->type == mod_brushq3)
8536 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8537 colorscale *= r_refdef.lightmapintensity;
8538 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8539 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8540 // basic lit geometry
8541 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]);
8542 // add pants/shirt if needed
8543 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8544 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]);
8545 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8546 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]);
8547 // now add ambient passes if needed
8548 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8550 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]);
8551 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8552 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]);
8553 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8554 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]);
8557 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8558 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]);
8559 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8561 // if this is opaque use alpha blend which will darken the earlier
8564 // if this is an alpha blended material, all the earlier passes
8565 // were darkened by fog already, so we only need to add the fog
8566 // color ontop through the fog mask texture
8568 // if this is an additive blended material, all the earlier passes
8569 // were darkened by fog already, and we should not add fog color
8570 // (because the background was not darkened, there is no fog color
8571 // that was lost behind it).
8572 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]);
8579 rsurfacestate_t rsurface;
8581 void RSurf_ActiveWorldEntity(void)
8583 dp_model_t *model = r_refdef.scene.worldmodel;
8584 //if (rsurface.entity == r_refdef.scene.worldentity)
8586 rsurface.entity = r_refdef.scene.worldentity;
8587 rsurface.skeleton = NULL;
8588 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8589 rsurface.ent_skinnum = 0;
8590 rsurface.ent_qwskin = -1;
8591 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8592 rsurface.shadertime = r_refdef.scene.time;
8593 rsurface.matrix = identitymatrix;
8594 rsurface.inversematrix = identitymatrix;
8595 rsurface.matrixscale = 1;
8596 rsurface.inversematrixscale = 1;
8597 R_EntityMatrix(&identitymatrix);
8598 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8599 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8600 rsurface.fograngerecip = r_refdef.fograngerecip;
8601 rsurface.fogheightfade = r_refdef.fogheightfade;
8602 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8603 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8604 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8605 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8606 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8607 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8608 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8609 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8610 rsurface.colormod[3] = 1;
8611 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);
8612 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8613 rsurface.frameblend[0].lerp = 1;
8614 rsurface.ent_alttextures = false;
8615 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8616 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8617 rsurface.entityskeletaltransform3x4 = NULL;
8618 rsurface.entityskeletaltransform3x4buffer = NULL;
8619 rsurface.entityskeletaltransform3x4offset = 0;
8620 rsurface.entityskeletaltransform3x4size = 0;;
8621 rsurface.entityskeletalnumtransforms = 0;
8622 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8623 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8624 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8625 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8626 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8627 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8628 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8629 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8630 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8631 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8632 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8633 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8634 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8635 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8636 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8637 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8638 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8639 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8640 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8641 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8642 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8643 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8644 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8645 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8646 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8647 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8648 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8649 rsurface.modelelement3i = model->surfmesh.data_element3i;
8650 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8651 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8652 rsurface.modelelement3s = model->surfmesh.data_element3s;
8653 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8654 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8655 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8656 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8657 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8658 rsurface.modelsurfaces = model->data_surfaces;
8659 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8660 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8661 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8662 rsurface.modelgeneratedvertex = false;
8663 rsurface.batchgeneratedvertex = false;
8664 rsurface.batchfirstvertex = 0;
8665 rsurface.batchnumvertices = 0;
8666 rsurface.batchfirsttriangle = 0;
8667 rsurface.batchnumtriangles = 0;
8668 rsurface.batchvertex3f = NULL;
8669 rsurface.batchvertex3f_vertexbuffer = NULL;
8670 rsurface.batchvertex3f_bufferoffset = 0;
8671 rsurface.batchsvector3f = NULL;
8672 rsurface.batchsvector3f_vertexbuffer = NULL;
8673 rsurface.batchsvector3f_bufferoffset = 0;
8674 rsurface.batchtvector3f = NULL;
8675 rsurface.batchtvector3f_vertexbuffer = NULL;
8676 rsurface.batchtvector3f_bufferoffset = 0;
8677 rsurface.batchnormal3f = NULL;
8678 rsurface.batchnormal3f_vertexbuffer = NULL;
8679 rsurface.batchnormal3f_bufferoffset = 0;
8680 rsurface.batchlightmapcolor4f = NULL;
8681 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8682 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8683 rsurface.batchtexcoordtexture2f = NULL;
8684 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8685 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8686 rsurface.batchtexcoordlightmap2f = NULL;
8687 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8688 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8689 rsurface.batchskeletalindex4ub = NULL;
8690 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8691 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8692 rsurface.batchskeletalweight4ub = NULL;
8693 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8694 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8695 rsurface.batchvertexmesh = NULL;
8696 rsurface.batchvertexmesh_vertexbuffer = NULL;
8697 rsurface.batchvertexmesh_bufferoffset = 0;
8698 rsurface.batchelement3i = NULL;
8699 rsurface.batchelement3i_indexbuffer = NULL;
8700 rsurface.batchelement3i_bufferoffset = 0;
8701 rsurface.batchelement3s = NULL;
8702 rsurface.batchelement3s_indexbuffer = NULL;
8703 rsurface.batchelement3s_bufferoffset = 0;
8704 rsurface.passcolor4f = NULL;
8705 rsurface.passcolor4f_vertexbuffer = NULL;
8706 rsurface.passcolor4f_bufferoffset = 0;
8707 rsurface.forcecurrenttextureupdate = false;
8710 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8712 dp_model_t *model = ent->model;
8713 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8715 rsurface.entity = (entity_render_t *)ent;
8716 rsurface.skeleton = ent->skeleton;
8717 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8718 rsurface.ent_skinnum = ent->skinnum;
8719 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;
8720 rsurface.ent_flags = ent->flags;
8721 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8722 rsurface.matrix = ent->matrix;
8723 rsurface.inversematrix = ent->inversematrix;
8724 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8725 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8726 R_EntityMatrix(&rsurface.matrix);
8727 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8728 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8729 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8730 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8731 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8732 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8733 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8734 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8735 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8736 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8737 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8738 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8739 rsurface.colormod[3] = ent->alpha;
8740 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8741 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8742 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8743 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8744 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8745 if (ent->model->brush.submodel && !prepass)
8747 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8748 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8750 // if the animcache code decided it should use the shader path, skip the deform step
8751 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8752 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8753 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8754 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8755 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8756 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8758 if (ent->animcache_vertex3f)
8760 r_refdef.stats[r_stat_batch_entitycache_count]++;
8761 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8762 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8763 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8764 rsurface.modelvertex3f = ent->animcache_vertex3f;
8765 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8766 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8767 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8768 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8769 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8770 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8771 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8772 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8773 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8774 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8775 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8776 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8777 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8778 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8780 else if (wanttangents)
8782 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8783 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8784 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8785 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8786 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8787 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8788 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8789 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8790 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8791 rsurface.modelvertexmesh = NULL;
8792 rsurface.modelvertexmesh_vertexbuffer = NULL;
8793 rsurface.modelvertexmesh_bufferoffset = 0;
8794 rsurface.modelvertex3f_vertexbuffer = NULL;
8795 rsurface.modelvertex3f_bufferoffset = 0;
8796 rsurface.modelvertex3f_vertexbuffer = 0;
8797 rsurface.modelvertex3f_bufferoffset = 0;
8798 rsurface.modelsvector3f_vertexbuffer = 0;
8799 rsurface.modelsvector3f_bufferoffset = 0;
8800 rsurface.modeltvector3f_vertexbuffer = 0;
8801 rsurface.modeltvector3f_bufferoffset = 0;
8802 rsurface.modelnormal3f_vertexbuffer = 0;
8803 rsurface.modelnormal3f_bufferoffset = 0;
8805 else if (wantnormals)
8807 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8808 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8809 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8810 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8811 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8812 rsurface.modelsvector3f = NULL;
8813 rsurface.modeltvector3f = NULL;
8814 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8815 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8816 rsurface.modelvertexmesh = NULL;
8817 rsurface.modelvertexmesh_vertexbuffer = NULL;
8818 rsurface.modelvertexmesh_bufferoffset = 0;
8819 rsurface.modelvertex3f_vertexbuffer = NULL;
8820 rsurface.modelvertex3f_bufferoffset = 0;
8821 rsurface.modelvertex3f_vertexbuffer = 0;
8822 rsurface.modelvertex3f_bufferoffset = 0;
8823 rsurface.modelsvector3f_vertexbuffer = 0;
8824 rsurface.modelsvector3f_bufferoffset = 0;
8825 rsurface.modeltvector3f_vertexbuffer = 0;
8826 rsurface.modeltvector3f_bufferoffset = 0;
8827 rsurface.modelnormal3f_vertexbuffer = 0;
8828 rsurface.modelnormal3f_bufferoffset = 0;
8832 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8833 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8834 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8835 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8836 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8837 rsurface.modelsvector3f = NULL;
8838 rsurface.modeltvector3f = NULL;
8839 rsurface.modelnormal3f = NULL;
8840 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8841 rsurface.modelvertexmesh = NULL;
8842 rsurface.modelvertexmesh_vertexbuffer = NULL;
8843 rsurface.modelvertexmesh_bufferoffset = 0;
8844 rsurface.modelvertex3f_vertexbuffer = NULL;
8845 rsurface.modelvertex3f_bufferoffset = 0;
8846 rsurface.modelvertex3f_vertexbuffer = 0;
8847 rsurface.modelvertex3f_bufferoffset = 0;
8848 rsurface.modelsvector3f_vertexbuffer = 0;
8849 rsurface.modelsvector3f_bufferoffset = 0;
8850 rsurface.modeltvector3f_vertexbuffer = 0;
8851 rsurface.modeltvector3f_bufferoffset = 0;
8852 rsurface.modelnormal3f_vertexbuffer = 0;
8853 rsurface.modelnormal3f_bufferoffset = 0;
8855 rsurface.modelgeneratedvertex = true;
8859 if (rsurface.entityskeletaltransform3x4)
8861 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8862 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8863 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8864 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8868 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8869 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8870 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8871 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8873 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8874 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8875 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8876 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8877 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8878 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8879 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8880 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8881 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8882 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8883 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8884 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8885 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8886 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8887 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8888 rsurface.modelgeneratedvertex = false;
8890 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8891 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8892 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8893 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8894 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8895 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8896 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8897 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8898 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8899 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8900 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8901 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8902 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8903 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8904 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8905 rsurface.modelelement3i = model->surfmesh.data_element3i;
8906 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8907 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8908 rsurface.modelelement3s = model->surfmesh.data_element3s;
8909 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8910 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8911 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8912 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8913 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8914 rsurface.modelsurfaces = model->data_surfaces;
8915 rsurface.batchgeneratedvertex = false;
8916 rsurface.batchfirstvertex = 0;
8917 rsurface.batchnumvertices = 0;
8918 rsurface.batchfirsttriangle = 0;
8919 rsurface.batchnumtriangles = 0;
8920 rsurface.batchvertex3f = NULL;
8921 rsurface.batchvertex3f_vertexbuffer = NULL;
8922 rsurface.batchvertex3f_bufferoffset = 0;
8923 rsurface.batchsvector3f = NULL;
8924 rsurface.batchsvector3f_vertexbuffer = NULL;
8925 rsurface.batchsvector3f_bufferoffset = 0;
8926 rsurface.batchtvector3f = NULL;
8927 rsurface.batchtvector3f_vertexbuffer = NULL;
8928 rsurface.batchtvector3f_bufferoffset = 0;
8929 rsurface.batchnormal3f = NULL;
8930 rsurface.batchnormal3f_vertexbuffer = NULL;
8931 rsurface.batchnormal3f_bufferoffset = 0;
8932 rsurface.batchlightmapcolor4f = NULL;
8933 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8934 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8935 rsurface.batchtexcoordtexture2f = NULL;
8936 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8937 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8938 rsurface.batchtexcoordlightmap2f = NULL;
8939 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8940 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8941 rsurface.batchskeletalindex4ub = NULL;
8942 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8943 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8944 rsurface.batchskeletalweight4ub = NULL;
8945 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8946 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8947 rsurface.batchvertexmesh = NULL;
8948 rsurface.batchvertexmesh_vertexbuffer = NULL;
8949 rsurface.batchvertexmesh_bufferoffset = 0;
8950 rsurface.batchelement3i = NULL;
8951 rsurface.batchelement3i_indexbuffer = NULL;
8952 rsurface.batchelement3i_bufferoffset = 0;
8953 rsurface.batchelement3s = NULL;
8954 rsurface.batchelement3s_indexbuffer = NULL;
8955 rsurface.batchelement3s_bufferoffset = 0;
8956 rsurface.passcolor4f = NULL;
8957 rsurface.passcolor4f_vertexbuffer = NULL;
8958 rsurface.passcolor4f_bufferoffset = 0;
8959 rsurface.forcecurrenttextureupdate = false;
8962 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)
8964 rsurface.entity = r_refdef.scene.worldentity;
8965 rsurface.skeleton = NULL;
8966 rsurface.ent_skinnum = 0;
8967 rsurface.ent_qwskin = -1;
8968 rsurface.ent_flags = entflags;
8969 rsurface.shadertime = r_refdef.scene.time - shadertime;
8970 rsurface.modelnumvertices = numvertices;
8971 rsurface.modelnumtriangles = numtriangles;
8972 rsurface.matrix = *matrix;
8973 rsurface.inversematrix = *inversematrix;
8974 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8975 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8976 R_EntityMatrix(&rsurface.matrix);
8977 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8978 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8979 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8980 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8981 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8982 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8983 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8984 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8985 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8986 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8987 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8988 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8989 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);
8990 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8991 rsurface.frameblend[0].lerp = 1;
8992 rsurface.ent_alttextures = false;
8993 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8994 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8995 rsurface.entityskeletaltransform3x4 = NULL;
8996 rsurface.entityskeletaltransform3x4buffer = NULL;
8997 rsurface.entityskeletaltransform3x4offset = 0;
8998 rsurface.entityskeletaltransform3x4size = 0;
8999 rsurface.entityskeletalnumtransforms = 0;
9000 r_refdef.stats[r_stat_batch_entitycustom_count]++;
9001 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
9002 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
9003 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
9006 rsurface.modelvertex3f = (float *)vertex3f;
9007 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9008 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9009 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9011 else if (wantnormals)
9013 rsurface.modelvertex3f = (float *)vertex3f;
9014 rsurface.modelsvector3f = NULL;
9015 rsurface.modeltvector3f = NULL;
9016 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9020 rsurface.modelvertex3f = (float *)vertex3f;
9021 rsurface.modelsvector3f = NULL;
9022 rsurface.modeltvector3f = NULL;
9023 rsurface.modelnormal3f = NULL;
9025 rsurface.modelvertexmesh = NULL;
9026 rsurface.modelvertexmesh_vertexbuffer = NULL;
9027 rsurface.modelvertexmesh_bufferoffset = 0;
9028 rsurface.modelvertex3f_vertexbuffer = 0;
9029 rsurface.modelvertex3f_bufferoffset = 0;
9030 rsurface.modelsvector3f_vertexbuffer = 0;
9031 rsurface.modelsvector3f_bufferoffset = 0;
9032 rsurface.modeltvector3f_vertexbuffer = 0;
9033 rsurface.modeltvector3f_bufferoffset = 0;
9034 rsurface.modelnormal3f_vertexbuffer = 0;
9035 rsurface.modelnormal3f_bufferoffset = 0;
9036 rsurface.modelgeneratedvertex = true;
9037 rsurface.modellightmapcolor4f = (float *)color4f;
9038 rsurface.modellightmapcolor4f_vertexbuffer = 0;
9039 rsurface.modellightmapcolor4f_bufferoffset = 0;
9040 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
9041 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9042 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9043 rsurface.modeltexcoordlightmap2f = NULL;
9044 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9045 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9046 rsurface.modelskeletalindex4ub = NULL;
9047 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
9048 rsurface.modelskeletalindex4ub_bufferoffset = 0;
9049 rsurface.modelskeletalweight4ub = NULL;
9050 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
9051 rsurface.modelskeletalweight4ub_bufferoffset = 0;
9052 rsurface.modelelement3i = (int *)element3i;
9053 rsurface.modelelement3i_indexbuffer = NULL;
9054 rsurface.modelelement3i_bufferoffset = 0;
9055 rsurface.modelelement3s = (unsigned short *)element3s;
9056 rsurface.modelelement3s_indexbuffer = NULL;
9057 rsurface.modelelement3s_bufferoffset = 0;
9058 rsurface.modellightmapoffsets = NULL;
9059 rsurface.modelsurfaces = NULL;
9060 rsurface.batchgeneratedvertex = false;
9061 rsurface.batchfirstvertex = 0;
9062 rsurface.batchnumvertices = 0;
9063 rsurface.batchfirsttriangle = 0;
9064 rsurface.batchnumtriangles = 0;
9065 rsurface.batchvertex3f = NULL;
9066 rsurface.batchvertex3f_vertexbuffer = NULL;
9067 rsurface.batchvertex3f_bufferoffset = 0;
9068 rsurface.batchsvector3f = NULL;
9069 rsurface.batchsvector3f_vertexbuffer = NULL;
9070 rsurface.batchsvector3f_bufferoffset = 0;
9071 rsurface.batchtvector3f = NULL;
9072 rsurface.batchtvector3f_vertexbuffer = NULL;
9073 rsurface.batchtvector3f_bufferoffset = 0;
9074 rsurface.batchnormal3f = NULL;
9075 rsurface.batchnormal3f_vertexbuffer = NULL;
9076 rsurface.batchnormal3f_bufferoffset = 0;
9077 rsurface.batchlightmapcolor4f = NULL;
9078 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9079 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9080 rsurface.batchtexcoordtexture2f = NULL;
9081 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9082 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9083 rsurface.batchtexcoordlightmap2f = NULL;
9084 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9085 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9086 rsurface.batchskeletalindex4ub = NULL;
9087 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9088 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9089 rsurface.batchskeletalweight4ub = NULL;
9090 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9091 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9092 rsurface.batchvertexmesh = NULL;
9093 rsurface.batchvertexmesh_vertexbuffer = NULL;
9094 rsurface.batchvertexmesh_bufferoffset = 0;
9095 rsurface.batchelement3i = NULL;
9096 rsurface.batchelement3i_indexbuffer = NULL;
9097 rsurface.batchelement3i_bufferoffset = 0;
9098 rsurface.batchelement3s = NULL;
9099 rsurface.batchelement3s_indexbuffer = NULL;
9100 rsurface.batchelement3s_bufferoffset = 0;
9101 rsurface.passcolor4f = NULL;
9102 rsurface.passcolor4f_vertexbuffer = NULL;
9103 rsurface.passcolor4f_bufferoffset = 0;
9104 rsurface.forcecurrenttextureupdate = true;
9106 if (rsurface.modelnumvertices && rsurface.modelelement3i)
9108 if ((wantnormals || wanttangents) && !normal3f)
9110 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9111 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9113 if (wanttangents && !svector3f)
9115 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9116 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9117 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9122 float RSurf_FogPoint(const float *v)
9124 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9125 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9126 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9127 float FogHeightFade = r_refdef.fogheightfade;
9129 unsigned int fogmasktableindex;
9130 if (r_refdef.fogplaneviewabove)
9131 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9133 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9134 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9135 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9138 float RSurf_FogVertex(const float *v)
9140 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9141 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9142 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9143 float FogHeightFade = rsurface.fogheightfade;
9145 unsigned int fogmasktableindex;
9146 if (r_refdef.fogplaneviewabove)
9147 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9149 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9150 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9151 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9154 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9157 for (i = 0;i < numelements;i++)
9158 outelement3i[i] = inelement3i[i] + adjust;
9161 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9162 extern cvar_t gl_vbo;
9163 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9171 int surfacefirsttriangle;
9172 int surfacenumtriangles;
9173 int surfacefirstvertex;
9174 int surfaceendvertex;
9175 int surfacenumvertices;
9176 int batchnumsurfaces = texturenumsurfaces;
9177 int batchnumvertices;
9178 int batchnumtriangles;
9182 qboolean dynamicvertex;
9185 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9188 q3shaderinfo_deform_t *deform;
9189 const msurface_t *surface, *firstsurface;
9190 r_vertexmesh_t *vertexmesh;
9191 if (!texturenumsurfaces)
9193 // find vertex range of this surface batch
9195 firstsurface = texturesurfacelist[0];
9196 firsttriangle = firstsurface->num_firsttriangle;
9197 batchnumvertices = 0;
9198 batchnumtriangles = 0;
9199 firstvertex = endvertex = firstsurface->num_firstvertex;
9200 for (i = 0;i < texturenumsurfaces;i++)
9202 surface = texturesurfacelist[i];
9203 if (surface != firstsurface + i)
9205 surfacefirstvertex = surface->num_firstvertex;
9206 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9207 surfacenumvertices = surface->num_vertices;
9208 surfacenumtriangles = surface->num_triangles;
9209 if (firstvertex > surfacefirstvertex)
9210 firstvertex = surfacefirstvertex;
9211 if (endvertex < surfaceendvertex)
9212 endvertex = surfaceendvertex;
9213 batchnumvertices += surfacenumvertices;
9214 batchnumtriangles += surfacenumtriangles;
9217 r_refdef.stats[r_stat_batch_batches]++;
9219 r_refdef.stats[r_stat_batch_withgaps]++;
9220 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9221 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9222 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9224 // we now know the vertex range used, and if there are any gaps in it
9225 rsurface.batchfirstvertex = firstvertex;
9226 rsurface.batchnumvertices = endvertex - firstvertex;
9227 rsurface.batchfirsttriangle = firsttriangle;
9228 rsurface.batchnumtriangles = batchnumtriangles;
9230 // this variable holds flags for which properties have been updated that
9231 // may require regenerating vertexmesh array...
9234 // check if any dynamic vertex processing must occur
9235 dynamicvertex = false;
9237 // a cvar to force the dynamic vertex path to be taken, for debugging
9238 if (r_batch_debugdynamicvertexpath.integer)
9242 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9243 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9244 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9245 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9247 dynamicvertex = true;
9250 // if there is a chance of animated vertex colors, it's a dynamic batch
9251 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9255 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9256 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9257 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9258 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9260 dynamicvertex = true;
9261 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9264 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9266 switch (deform->deform)
9269 case Q3DEFORM_PROJECTIONSHADOW:
9270 case Q3DEFORM_TEXT0:
9271 case Q3DEFORM_TEXT1:
9272 case Q3DEFORM_TEXT2:
9273 case Q3DEFORM_TEXT3:
9274 case Q3DEFORM_TEXT4:
9275 case Q3DEFORM_TEXT5:
9276 case Q3DEFORM_TEXT6:
9277 case Q3DEFORM_TEXT7:
9280 case Q3DEFORM_AUTOSPRITE:
9283 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9284 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9285 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9286 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9288 dynamicvertex = true;
9289 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9290 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9292 case Q3DEFORM_AUTOSPRITE2:
9295 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9296 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9297 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9298 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9300 dynamicvertex = true;
9301 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9302 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9304 case Q3DEFORM_NORMAL:
9307 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9308 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9309 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9310 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9312 dynamicvertex = true;
9313 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9314 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9317 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9318 break; // if wavefunc is a nop, ignore this transform
9321 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9322 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9323 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9324 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9326 dynamicvertex = true;
9327 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9328 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9330 case Q3DEFORM_BULGE:
9333 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9334 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9335 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9336 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9338 dynamicvertex = true;
9339 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9340 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9343 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9344 break; // if wavefunc is a nop, ignore this transform
9347 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9348 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9349 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9350 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9352 dynamicvertex = true;
9353 batchneed |= BATCHNEED_ARRAY_VERTEX;
9354 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9358 if (rsurface.texture->materialshaderpass)
9360 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9363 case Q3TCGEN_TEXTURE:
9365 case Q3TCGEN_LIGHTMAP:
9368 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9369 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9370 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9371 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9373 dynamicvertex = true;
9374 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9375 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9377 case Q3TCGEN_VECTOR:
9380 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9381 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9382 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9383 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9385 dynamicvertex = true;
9386 batchneed |= BATCHNEED_ARRAY_VERTEX;
9387 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9389 case Q3TCGEN_ENVIRONMENT:
9392 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9393 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9394 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9395 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9397 dynamicvertex = true;
9398 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9399 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9402 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9406 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9407 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9408 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9409 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9411 dynamicvertex = true;
9412 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9413 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9417 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9421 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9422 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9423 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9424 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9426 dynamicvertex = true;
9427 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9430 // when the model data has no vertex buffer (dynamic mesh), we need to
9432 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9433 batchneed |= BATCHNEED_NOGAPS;
9435 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9436 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9437 // we ensure this by treating the vertex batch as dynamic...
9438 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9442 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9443 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9444 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9445 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9447 dynamicvertex = true;
9452 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9453 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9454 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9455 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9456 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9457 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9458 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9459 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9462 // if needsupdate, we have to do a dynamic vertex batch for sure
9463 if (needsupdate & batchneed)
9467 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9468 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9469 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9470 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9472 dynamicvertex = true;
9475 // see if we need to build vertexmesh from arrays
9476 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9480 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9481 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9482 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9483 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9485 dynamicvertex = true;
9488 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9489 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9490 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9492 rsurface.batchvertex3f = rsurface.modelvertex3f;
9493 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9494 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9495 rsurface.batchsvector3f = rsurface.modelsvector3f;
9496 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9497 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9498 rsurface.batchtvector3f = rsurface.modeltvector3f;
9499 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9500 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9501 rsurface.batchnormal3f = rsurface.modelnormal3f;
9502 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9503 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9504 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9505 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9506 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9507 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9508 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9509 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9510 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9511 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9512 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9513 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9514 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9515 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9516 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9517 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9518 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9519 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9520 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9521 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9522 rsurface.batchelement3i = rsurface.modelelement3i;
9523 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9524 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9525 rsurface.batchelement3s = rsurface.modelelement3s;
9526 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9527 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9528 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9529 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9530 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9531 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9532 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9534 // if any dynamic vertex processing has to occur in software, we copy the
9535 // entire surface list together before processing to rebase the vertices
9536 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9538 // if any gaps exist and we do not have a static vertex buffer, we have to
9539 // copy the surface list together to avoid wasting upload bandwidth on the
9540 // vertices in the gaps.
9542 // if gaps exist and we have a static vertex buffer, we can choose whether
9543 // to combine the index buffer ranges into one dynamic index buffer or
9544 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9546 // in many cases the batch is reduced to one draw call.
9548 rsurface.batchmultidraw = false;
9549 rsurface.batchmultidrawnumsurfaces = 0;
9550 rsurface.batchmultidrawsurfacelist = NULL;
9554 // static vertex data, just set pointers...
9555 rsurface.batchgeneratedvertex = false;
9556 // if there are gaps, we want to build a combined index buffer,
9557 // otherwise use the original static buffer with an appropriate offset
9560 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9561 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9562 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9563 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9564 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9566 rsurface.batchmultidraw = true;
9567 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9568 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9571 // build a new triangle elements array for this batch
9572 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9573 rsurface.batchfirsttriangle = 0;
9575 for (i = 0;i < texturenumsurfaces;i++)
9577 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9578 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9579 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9580 numtriangles += surfacenumtriangles;
9582 rsurface.batchelement3i_indexbuffer = NULL;
9583 rsurface.batchelement3i_bufferoffset = 0;
9584 rsurface.batchelement3s = NULL;
9585 rsurface.batchelement3s_indexbuffer = NULL;
9586 rsurface.batchelement3s_bufferoffset = 0;
9587 if (endvertex <= 65536)
9589 // make a 16bit (unsigned short) index array if possible
9590 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9591 for (i = 0;i < numtriangles*3;i++)
9592 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9594 // upload buffer data for the copytriangles batch
9595 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9597 if (rsurface.batchelement3s)
9598 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9599 else if (rsurface.batchelement3i)
9600 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9605 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9606 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9607 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9608 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9613 // something needs software processing, do it for real...
9614 // we only directly handle separate array data in this case and then
9615 // generate interleaved data if needed...
9616 rsurface.batchgeneratedvertex = true;
9617 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9618 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9619 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9620 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9622 // now copy the vertex data into a combined array and make an index array
9623 // (this is what Quake3 does all the time)
9624 // we also apply any skeletal animation here that would have been done in
9625 // the vertex shader, because most of the dynamic vertex animation cases
9626 // need actual vertex positions and normals
9627 //if (dynamicvertex)
9629 rsurface.batchvertexmesh = NULL;
9630 rsurface.batchvertexmesh_vertexbuffer = NULL;
9631 rsurface.batchvertexmesh_bufferoffset = 0;
9632 rsurface.batchvertex3f = NULL;
9633 rsurface.batchvertex3f_vertexbuffer = NULL;
9634 rsurface.batchvertex3f_bufferoffset = 0;
9635 rsurface.batchsvector3f = NULL;
9636 rsurface.batchsvector3f_vertexbuffer = NULL;
9637 rsurface.batchsvector3f_bufferoffset = 0;
9638 rsurface.batchtvector3f = NULL;
9639 rsurface.batchtvector3f_vertexbuffer = NULL;
9640 rsurface.batchtvector3f_bufferoffset = 0;
9641 rsurface.batchnormal3f = NULL;
9642 rsurface.batchnormal3f_vertexbuffer = NULL;
9643 rsurface.batchnormal3f_bufferoffset = 0;
9644 rsurface.batchlightmapcolor4f = NULL;
9645 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9646 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9647 rsurface.batchtexcoordtexture2f = NULL;
9648 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9649 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9650 rsurface.batchtexcoordlightmap2f = NULL;
9651 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9652 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9653 rsurface.batchskeletalindex4ub = NULL;
9654 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9655 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9656 rsurface.batchskeletalweight4ub = NULL;
9657 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9658 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9659 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9660 rsurface.batchelement3i_indexbuffer = NULL;
9661 rsurface.batchelement3i_bufferoffset = 0;
9662 rsurface.batchelement3s = NULL;
9663 rsurface.batchelement3s_indexbuffer = NULL;
9664 rsurface.batchelement3s_bufferoffset = 0;
9665 rsurface.batchskeletaltransform3x4buffer = NULL;
9666 rsurface.batchskeletaltransform3x4offset = 0;
9667 rsurface.batchskeletaltransform3x4size = 0;
9668 // we'll only be setting up certain arrays as needed
9669 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9670 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9671 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9672 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9673 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9674 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9675 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9677 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9678 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9680 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9681 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9682 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9683 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9684 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9685 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9686 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9688 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9689 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9693 for (i = 0;i < texturenumsurfaces;i++)
9695 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9696 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9697 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9698 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9699 // copy only the data requested
9700 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9701 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9702 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9704 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9706 if (rsurface.batchvertex3f)
9707 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9709 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9711 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9713 if (rsurface.modelnormal3f)
9714 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9716 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9718 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9720 if (rsurface.modelsvector3f)
9722 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9723 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9727 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9728 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9731 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9733 if (rsurface.modellightmapcolor4f)
9734 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9736 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9738 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9740 if (rsurface.modeltexcoordtexture2f)
9741 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9743 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9745 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9747 if (rsurface.modeltexcoordlightmap2f)
9748 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9750 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9752 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9754 if (rsurface.modelskeletalindex4ub)
9756 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9757 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9761 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9762 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9763 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9764 for (j = 0;j < surfacenumvertices;j++)
9769 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9770 numvertices += surfacenumvertices;
9771 numtriangles += surfacenumtriangles;
9774 // generate a 16bit index array as well if possible
9775 // (in general, dynamic batches fit)
9776 if (numvertices <= 65536)
9778 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9779 for (i = 0;i < numtriangles*3;i++)
9780 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9783 // since we've copied everything, the batch now starts at 0
9784 rsurface.batchfirstvertex = 0;
9785 rsurface.batchnumvertices = batchnumvertices;
9786 rsurface.batchfirsttriangle = 0;
9787 rsurface.batchnumtriangles = batchnumtriangles;
9790 // apply skeletal animation that would have been done in the vertex shader
9791 if (rsurface.batchskeletaltransform3x4)
9793 const unsigned char *si;
9794 const unsigned char *sw;
9796 const float *b = rsurface.batchskeletaltransform3x4;
9797 float *vp, *vs, *vt, *vn;
9799 float m[3][4], n[3][4];
9800 float tp[3], ts[3], tt[3], tn[3];
9801 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9802 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9803 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9804 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9805 si = rsurface.batchskeletalindex4ub;
9806 sw = rsurface.batchskeletalweight4ub;
9807 vp = rsurface.batchvertex3f;
9808 vs = rsurface.batchsvector3f;
9809 vt = rsurface.batchtvector3f;
9810 vn = rsurface.batchnormal3f;
9811 memset(m[0], 0, sizeof(m));
9812 memset(n[0], 0, sizeof(n));
9813 for (i = 0;i < batchnumvertices;i++)
9815 t[0] = b + si[0]*12;
9818 // common case - only one matrix
9832 else if (sw[2] + sw[3])
9835 t[1] = b + si[1]*12;
9836 t[2] = b + si[2]*12;
9837 t[3] = b + si[3]*12;
9838 w[0] = sw[0] * (1.0f / 255.0f);
9839 w[1] = sw[1] * (1.0f / 255.0f);
9840 w[2] = sw[2] * (1.0f / 255.0f);
9841 w[3] = sw[3] * (1.0f / 255.0f);
9842 // blend the matrices
9843 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9844 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9845 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9846 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9847 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9848 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9849 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9850 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9851 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9852 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9853 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9854 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9859 t[1] = b + si[1]*12;
9860 w[0] = sw[0] * (1.0f / 255.0f);
9861 w[1] = sw[1] * (1.0f / 255.0f);
9862 // blend the matrices
9863 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9864 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9865 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9866 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9867 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9868 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9869 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9870 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9871 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9872 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9873 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9874 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9878 // modify the vertex
9880 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9881 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9882 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9886 // the normal transformation matrix is a set of cross products...
9887 CrossProduct(m[1], m[2], n[0]);
9888 CrossProduct(m[2], m[0], n[1]);
9889 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9891 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9892 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9893 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9894 VectorNormalize(vn);
9899 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9900 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9901 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9902 VectorNormalize(vs);
9905 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9906 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9907 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9908 VectorNormalize(vt);
9913 rsurface.batchskeletaltransform3x4 = NULL;
9914 rsurface.batchskeletalnumtransforms = 0;
9917 // q1bsp surfaces rendered in vertex color mode have to have colors
9918 // calculated based on lightstyles
9919 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9921 // generate color arrays for the surfaces in this list
9926 const unsigned char *lm;
9927 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9928 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9929 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9931 for (i = 0;i < texturenumsurfaces;i++)
9933 surface = texturesurfacelist[i];
9934 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9935 surfacenumvertices = surface->num_vertices;
9936 if (surface->lightmapinfo->samples)
9938 for (j = 0;j < surfacenumvertices;j++)
9940 lm = surface->lightmapinfo->samples + offsets[j];
9941 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9942 VectorScale(lm, scale, c);
9943 if (surface->lightmapinfo->styles[1] != 255)
9945 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9947 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9948 VectorMA(c, scale, lm, c);
9949 if (surface->lightmapinfo->styles[2] != 255)
9952 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9953 VectorMA(c, scale, lm, c);
9954 if (surface->lightmapinfo->styles[3] != 255)
9957 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9958 VectorMA(c, scale, lm, c);
9965 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);
9971 for (j = 0;j < surfacenumvertices;j++)
9973 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9980 // if vertices are deformed (sprite flares and things in maps, possibly
9981 // water waves, bulges and other deformations), modify the copied vertices
9983 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9986 switch (deform->deform)
9989 case Q3DEFORM_PROJECTIONSHADOW:
9990 case Q3DEFORM_TEXT0:
9991 case Q3DEFORM_TEXT1:
9992 case Q3DEFORM_TEXT2:
9993 case Q3DEFORM_TEXT3:
9994 case Q3DEFORM_TEXT4:
9995 case Q3DEFORM_TEXT5:
9996 case Q3DEFORM_TEXT6:
9997 case Q3DEFORM_TEXT7:
10000 case Q3DEFORM_AUTOSPRITE:
10001 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10002 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10003 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10004 VectorNormalize(newforward);
10005 VectorNormalize(newright);
10006 VectorNormalize(newup);
10007 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10008 // rsurface.batchvertex3f_vertexbuffer = NULL;
10009 // rsurface.batchvertex3f_bufferoffset = 0;
10010 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
10011 // rsurface.batchsvector3f_vertexbuffer = NULL;
10012 // rsurface.batchsvector3f_bufferoffset = 0;
10013 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
10014 // rsurface.batchtvector3f_vertexbuffer = NULL;
10015 // rsurface.batchtvector3f_bufferoffset = 0;
10016 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10017 // rsurface.batchnormal3f_vertexbuffer = NULL;
10018 // rsurface.batchnormal3f_bufferoffset = 0;
10019 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
10020 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
10021 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10022 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
10023 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);
10024 // a single autosprite surface can contain multiple sprites...
10025 for (j = 0;j < batchnumvertices - 3;j += 4)
10027 VectorClear(center);
10028 for (i = 0;i < 4;i++)
10029 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10030 VectorScale(center, 0.25f, center);
10031 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10032 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10033 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10034 for (i = 0;i < 4;i++)
10036 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10037 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
10040 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
10041 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 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);
10044 case Q3DEFORM_AUTOSPRITE2:
10045 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10046 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10047 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10048 VectorNormalize(newforward);
10049 VectorNormalize(newright);
10050 VectorNormalize(newup);
10051 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10052 // rsurface.batchvertex3f_vertexbuffer = NULL;
10053 // rsurface.batchvertex3f_bufferoffset = 0;
10055 const float *v1, *v2;
10065 memset(shortest, 0, sizeof(shortest));
10066 // a single autosprite surface can contain multiple sprites...
10067 for (j = 0;j < batchnumvertices - 3;j += 4)
10069 VectorClear(center);
10070 for (i = 0;i < 4;i++)
10071 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10072 VectorScale(center, 0.25f, center);
10073 // find the two shortest edges, then use them to define the
10074 // axis vectors for rotating around the central axis
10075 for (i = 0;i < 6;i++)
10077 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10078 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10079 l = VectorDistance2(v1, v2);
10080 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10081 if (v1[2] != v2[2])
10082 l += (1.0f / 1024.0f);
10083 if (shortest[0].length2 > l || i == 0)
10085 shortest[1] = shortest[0];
10086 shortest[0].length2 = l;
10087 shortest[0].v1 = v1;
10088 shortest[0].v2 = v2;
10090 else if (shortest[1].length2 > l || i == 1)
10092 shortest[1].length2 = l;
10093 shortest[1].v1 = v1;
10094 shortest[1].v2 = v2;
10097 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10098 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10099 // this calculates the right vector from the shortest edge
10100 // and the up vector from the edge midpoints
10101 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10102 VectorNormalize(right);
10103 VectorSubtract(end, start, up);
10104 VectorNormalize(up);
10105 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10106 VectorSubtract(rsurface.localvieworigin, center, forward);
10107 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10108 VectorNegate(forward, forward);
10109 VectorReflect(forward, 0, up, forward);
10110 VectorNormalize(forward);
10111 CrossProduct(up, forward, newright);
10112 VectorNormalize(newright);
10113 // rotate the quad around the up axis vector, this is made
10114 // especially easy by the fact we know the quad is flat,
10115 // so we only have to subtract the center position and
10116 // measure distance along the right vector, and then
10117 // multiply that by the newright vector and add back the
10119 // we also need to subtract the old position to undo the
10120 // displacement from the center, which we do with a
10121 // DotProduct, the subtraction/addition of center is also
10122 // optimized into DotProducts here
10123 l = DotProduct(right, center);
10124 for (i = 0;i < 4;i++)
10126 v1 = rsurface.batchvertex3f + 3*(j+i);
10127 f = DotProduct(right, v1) - l;
10128 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10132 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10134 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10135 // rsurface.batchnormal3f_vertexbuffer = NULL;
10136 // rsurface.batchnormal3f_bufferoffset = 0;
10137 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10139 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10141 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10142 // rsurface.batchsvector3f_vertexbuffer = NULL;
10143 // rsurface.batchsvector3f_bufferoffset = 0;
10144 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10145 // rsurface.batchtvector3f_vertexbuffer = NULL;
10146 // rsurface.batchtvector3f_bufferoffset = 0;
10147 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);
10150 case Q3DEFORM_NORMAL:
10151 // deform the normals to make reflections wavey
10152 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10153 rsurface.batchnormal3f_vertexbuffer = NULL;
10154 rsurface.batchnormal3f_bufferoffset = 0;
10155 for (j = 0;j < batchnumvertices;j++)
10158 float *normal = rsurface.batchnormal3f + 3*j;
10159 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10160 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10161 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10162 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10163 VectorNormalize(normal);
10165 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10167 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10168 // rsurface.batchsvector3f_vertexbuffer = NULL;
10169 // rsurface.batchsvector3f_bufferoffset = 0;
10170 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10171 // rsurface.batchtvector3f_vertexbuffer = NULL;
10172 // rsurface.batchtvector3f_bufferoffset = 0;
10173 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);
10176 case Q3DEFORM_WAVE:
10177 // deform vertex array to make wavey water and flags and such
10178 waveparms[0] = deform->waveparms[0];
10179 waveparms[1] = deform->waveparms[1];
10180 waveparms[2] = deform->waveparms[2];
10181 waveparms[3] = deform->waveparms[3];
10182 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10183 break; // if wavefunc is a nop, don't make a dynamic vertex array
10184 // this is how a divisor of vertex influence on deformation
10185 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10186 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10187 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10188 // rsurface.batchvertex3f_vertexbuffer = NULL;
10189 // rsurface.batchvertex3f_bufferoffset = 0;
10190 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10191 // rsurface.batchnormal3f_vertexbuffer = NULL;
10192 // rsurface.batchnormal3f_bufferoffset = 0;
10193 for (j = 0;j < batchnumvertices;j++)
10195 // if the wavefunc depends on time, evaluate it per-vertex
10198 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10199 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10201 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10203 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10204 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10205 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10207 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10208 // rsurface.batchsvector3f_vertexbuffer = NULL;
10209 // rsurface.batchsvector3f_bufferoffset = 0;
10210 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10211 // rsurface.batchtvector3f_vertexbuffer = NULL;
10212 // rsurface.batchtvector3f_bufferoffset = 0;
10213 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);
10216 case Q3DEFORM_BULGE:
10217 // deform vertex array to make the surface have moving bulges
10218 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10219 // rsurface.batchvertex3f_vertexbuffer = NULL;
10220 // rsurface.batchvertex3f_bufferoffset = 0;
10221 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10222 // rsurface.batchnormal3f_vertexbuffer = NULL;
10223 // rsurface.batchnormal3f_bufferoffset = 0;
10224 for (j = 0;j < batchnumvertices;j++)
10226 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10227 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10229 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10230 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10231 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10233 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10234 // rsurface.batchsvector3f_vertexbuffer = NULL;
10235 // rsurface.batchsvector3f_bufferoffset = 0;
10236 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10237 // rsurface.batchtvector3f_vertexbuffer = NULL;
10238 // rsurface.batchtvector3f_bufferoffset = 0;
10239 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);
10242 case Q3DEFORM_MOVE:
10243 // deform vertex array
10244 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10245 break; // if wavefunc is a nop, don't make a dynamic vertex array
10246 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10247 VectorScale(deform->parms, scale, waveparms);
10248 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10249 // rsurface.batchvertex3f_vertexbuffer = NULL;
10250 // rsurface.batchvertex3f_bufferoffset = 0;
10251 for (j = 0;j < batchnumvertices;j++)
10252 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10257 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10259 // generate texcoords based on the chosen texcoord source
10260 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10263 case Q3TCGEN_TEXTURE:
10265 case Q3TCGEN_LIGHTMAP:
10266 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10267 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10268 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10269 if (rsurface.batchtexcoordlightmap2f)
10270 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10272 case Q3TCGEN_VECTOR:
10273 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10274 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10275 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10276 for (j = 0;j < batchnumvertices;j++)
10278 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10279 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10282 case Q3TCGEN_ENVIRONMENT:
10283 // make environment reflections using a spheremap
10284 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10285 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10286 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10287 for (j = 0;j < batchnumvertices;j++)
10289 // identical to Q3A's method, but executed in worldspace so
10290 // carried models can be shiny too
10292 float viewer[3], d, reflected[3], worldreflected[3];
10294 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10295 // VectorNormalize(viewer);
10297 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10299 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10300 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10301 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10302 // note: this is proportinal to viewer, so we can normalize later
10304 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10305 VectorNormalize(worldreflected);
10307 // note: this sphere map only uses world x and z!
10308 // so positive and negative y will LOOK THE SAME.
10309 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10310 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10314 // the only tcmod that needs software vertex processing is turbulent, so
10315 // check for it here and apply the changes if needed
10316 // and we only support that as the first one
10317 // (handling a mixture of turbulent and other tcmods would be problematic
10318 // without punting it entirely to a software path)
10319 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10321 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10322 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10323 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10324 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10325 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10326 for (j = 0;j < batchnumvertices;j++)
10328 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);
10329 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10334 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10336 // convert the modified arrays to vertex structs
10337 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10338 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10339 // rsurface.batchvertexmesh_bufferoffset = 0;
10340 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10341 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10342 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10343 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10344 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10345 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10346 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10348 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10350 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10351 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10354 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10355 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10356 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10357 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10358 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10359 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10360 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10361 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10362 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10363 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10365 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10367 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10368 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10373 // upload buffer data for the dynamic batch
10374 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10376 if (rsurface.batchvertexmesh)
10377 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10380 if (rsurface.batchvertex3f)
10381 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10382 if (rsurface.batchsvector3f)
10383 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10384 if (rsurface.batchtvector3f)
10385 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10386 if (rsurface.batchnormal3f)
10387 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10388 if (rsurface.batchlightmapcolor4f)
10389 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10390 if (rsurface.batchtexcoordtexture2f)
10391 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10392 if (rsurface.batchtexcoordlightmap2f)
10393 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10394 if (rsurface.batchskeletalindex4ub)
10395 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10396 if (rsurface.batchskeletalweight4ub)
10397 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10399 if (rsurface.batchelement3s)
10400 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10401 else if (rsurface.batchelement3i)
10402 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10406 void RSurf_DrawBatch(void)
10408 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10409 // through the pipeline, killing it earlier in the pipeline would have
10410 // per-surface overhead rather than per-batch overhead, so it's best to
10411 // reject it here, before it hits glDraw.
10412 if (rsurface.batchnumtriangles == 0)
10415 // batch debugging code
10416 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10422 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10423 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10426 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10428 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10430 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10431 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);
10438 if (rsurface.batchmultidraw)
10440 // issue multiple draws rather than copying index data
10441 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10442 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10443 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10444 for (i = 0;i < numsurfaces;)
10446 // combine consecutive surfaces as one draw
10447 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10448 if (surfacelist[j] != surfacelist[k] + 1)
10450 firstvertex = surfacelist[i]->num_firstvertex;
10451 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10452 firsttriangle = surfacelist[i]->num_firsttriangle;
10453 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10454 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);
10460 // there is only one consecutive run of index data (may have been combined)
10461 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);
10465 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10467 // pick the closest matching water plane
10468 int planeindex, vertexindex, bestplaneindex = -1;
10472 r_waterstate_waterplane_t *p;
10473 qboolean prepared = false;
10475 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10477 if(p->camera_entity != rsurface.texture->camera_entity)
10482 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10484 if(rsurface.batchnumvertices == 0)
10487 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10489 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10490 d += fabs(PlaneDiff(vert, &p->plane));
10492 if (bestd > d || bestplaneindex < 0)
10495 bestplaneindex = planeindex;
10498 return bestplaneindex;
10499 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10500 // this situation though, as it might be better to render single larger
10501 // batches with useless stuff (backface culled for example) than to
10502 // render multiple smaller batches
10505 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10508 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10509 rsurface.passcolor4f_vertexbuffer = 0;
10510 rsurface.passcolor4f_bufferoffset = 0;
10511 for (i = 0;i < rsurface.batchnumvertices;i++)
10512 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10515 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10522 if (rsurface.passcolor4f)
10524 // generate color arrays
10525 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10526 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10527 rsurface.passcolor4f_vertexbuffer = 0;
10528 rsurface.passcolor4f_bufferoffset = 0;
10529 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)
10531 f = RSurf_FogVertex(v);
10540 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10541 rsurface.passcolor4f_vertexbuffer = 0;
10542 rsurface.passcolor4f_bufferoffset = 0;
10543 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10545 f = RSurf_FogVertex(v);
10554 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10561 if (!rsurface.passcolor4f)
10563 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10564 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10565 rsurface.passcolor4f_vertexbuffer = 0;
10566 rsurface.passcolor4f_bufferoffset = 0;
10567 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)
10569 f = RSurf_FogVertex(v);
10570 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10571 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10572 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10577 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10582 if (!rsurface.passcolor4f)
10584 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10585 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10586 rsurface.passcolor4f_vertexbuffer = 0;
10587 rsurface.passcolor4f_bufferoffset = 0;
10588 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10597 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10602 if (!rsurface.passcolor4f)
10604 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10605 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10606 rsurface.passcolor4f_vertexbuffer = 0;
10607 rsurface.passcolor4f_bufferoffset = 0;
10608 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10610 c2[0] = c[0] + r_refdef.scene.ambient;
10611 c2[1] = c[1] + r_refdef.scene.ambient;
10612 c2[2] = c[2] + r_refdef.scene.ambient;
10617 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10620 rsurface.passcolor4f = NULL;
10621 rsurface.passcolor4f_vertexbuffer = 0;
10622 rsurface.passcolor4f_bufferoffset = 0;
10623 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10624 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10625 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10626 GL_Color(r, g, b, a);
10627 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10628 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10629 R_Mesh_TexMatrix(0, NULL);
10633 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10635 // TODO: optimize applyfog && applycolor case
10636 // just apply fog if necessary, and tint the fog color array if necessary
10637 rsurface.passcolor4f = NULL;
10638 rsurface.passcolor4f_vertexbuffer = 0;
10639 rsurface.passcolor4f_bufferoffset = 0;
10640 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10641 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10642 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10643 GL_Color(r, g, b, a);
10647 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10650 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10651 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10652 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10653 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10654 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10655 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10656 GL_Color(r, g, b, a);
10660 static void RSurf_DrawBatch_GL11_ClampColor(void)
10665 if (!rsurface.passcolor4f)
10667 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10669 c2[0] = bound(0.0f, c1[0], 1.0f);
10670 c2[1] = bound(0.0f, c1[1], 1.0f);
10671 c2[2] = bound(0.0f, c1[2], 1.0f);
10672 c2[3] = bound(0.0f, c1[3], 1.0f);
10676 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10686 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10687 rsurface.passcolor4f_vertexbuffer = 0;
10688 rsurface.passcolor4f_bufferoffset = 0;
10689 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)
10691 f = -DotProduct(r_refdef.view.forward, n);
10693 f = f * 0.85 + 0.15; // work around so stuff won't get black
10694 f *= r_refdef.lightmapintensity;
10695 Vector4Set(c, f, f, f, 1);
10699 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10701 RSurf_DrawBatch_GL11_ApplyFakeLight();
10702 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10703 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10704 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10705 GL_Color(r, g, b, a);
10709 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10717 vec3_t ambientcolor;
10718 vec3_t diffusecolor;
10722 VectorCopy(rsurface.modellight_lightdir, lightdir);
10723 f = 0.5f * r_refdef.lightmapintensity;
10724 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10725 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10726 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10727 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10728 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10729 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10731 if (VectorLength2(diffusecolor) > 0)
10733 // q3-style directional shading
10734 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10735 rsurface.passcolor4f_vertexbuffer = 0;
10736 rsurface.passcolor4f_bufferoffset = 0;
10737 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)
10739 if ((f = DotProduct(n, lightdir)) > 0)
10740 VectorMA(ambientcolor, f, diffusecolor, c);
10742 VectorCopy(ambientcolor, c);
10749 *applycolor = false;
10753 *r = ambientcolor[0];
10754 *g = ambientcolor[1];
10755 *b = ambientcolor[2];
10756 rsurface.passcolor4f = NULL;
10757 rsurface.passcolor4f_vertexbuffer = 0;
10758 rsurface.passcolor4f_bufferoffset = 0;
10762 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10764 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10765 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10766 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10767 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10768 GL_Color(r, g, b, a);
10772 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10780 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10781 rsurface.passcolor4f_vertexbuffer = 0;
10782 rsurface.passcolor4f_bufferoffset = 0;
10784 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10786 f = 1 - RSurf_FogVertex(v);
10794 void RSurf_SetupDepthAndCulling(void)
10796 // submodels are biased to avoid z-fighting with world surfaces that they
10797 // may be exactly overlapping (avoids z-fighting artifacts on certain
10798 // doors and things in Quake maps)
10799 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10800 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10801 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10802 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10805 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10807 // transparent sky would be ridiculous
10808 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10810 R_SetupShader_Generic_NoTexture(false, false);
10811 skyrenderlater = true;
10812 RSurf_SetupDepthAndCulling();
10813 GL_DepthMask(true);
10814 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10815 // skymasking on them, and Quake3 never did sky masking (unlike
10816 // software Quake and software Quake2), so disable the sky masking
10817 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10818 // and skymasking also looks very bad when noclipping outside the
10819 // level, so don't use it then either.
10820 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10822 R_Mesh_ResetTextureState();
10823 if (skyrendermasked)
10825 R_SetupShader_DepthOrShadow(false, false, false);
10826 // depth-only (masking)
10827 GL_ColorMask(0,0,0,0);
10828 // just to make sure that braindead drivers don't draw
10829 // anything despite that colormask...
10830 GL_BlendFunc(GL_ZERO, GL_ONE);
10831 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10832 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10836 R_SetupShader_Generic_NoTexture(false, false);
10838 GL_BlendFunc(GL_ONE, GL_ZERO);
10839 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10840 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10841 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10844 if (skyrendermasked)
10845 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10847 R_Mesh_ResetTextureState();
10848 GL_Color(1, 1, 1, 1);
10851 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10852 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10853 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10855 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10859 // render screenspace normalmap to texture
10860 GL_DepthMask(true);
10861 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10866 // bind lightmap texture
10868 // water/refraction/reflection/camera surfaces have to be handled specially
10869 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10871 int start, end, startplaneindex;
10872 for (start = 0;start < texturenumsurfaces;start = end)
10874 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10875 if(startplaneindex < 0)
10877 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10878 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10882 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10884 // now that we have a batch using the same planeindex, render it
10885 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10887 // render water or distortion background
10888 GL_DepthMask(true);
10889 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);
10891 // blend surface on top
10892 GL_DepthMask(false);
10893 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10896 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10898 // render surface with reflection texture as input
10899 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10900 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);
10907 // render surface batch normally
10908 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10909 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);
10913 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10915 // OpenGL 1.3 path - anything not completely ancient
10916 qboolean applycolor;
10919 const texturelayer_t *layer;
10920 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);
10921 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10923 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10926 int layertexrgbscale;
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 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10941 layertexrgbscale = 4;
10942 VectorScale(layer->color, 0.25f, layercolor);
10944 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10946 layertexrgbscale = 2;
10947 VectorScale(layer->color, 0.5f, layercolor);
10951 layertexrgbscale = 1;
10952 VectorScale(layer->color, 1.0f, layercolor);
10954 layercolor[3] = layer->color[3];
10955 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10956 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10957 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10958 switch (layer->type)
10960 case TEXTURELAYERTYPE_LITTEXTURE:
10961 // single-pass lightmapped texture with 2x rgbscale
10962 R_Mesh_TexBind(0, r_texture_white);
10963 R_Mesh_TexMatrix(0, NULL);
10964 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10965 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10966 R_Mesh_TexBind(1, layer->texture);
10967 R_Mesh_TexMatrix(1, &layer->texmatrix);
10968 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10969 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10970 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10971 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10972 else if (FAKELIGHT_ENABLED)
10973 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10974 else if (rsurface.uselightmaptexture)
10975 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10977 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10979 case TEXTURELAYERTYPE_TEXTURE:
10980 // singletexture unlit texture with transparency support
10981 R_Mesh_TexBind(0, layer->texture);
10982 R_Mesh_TexMatrix(0, &layer->texmatrix);
10983 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10984 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10985 R_Mesh_TexBind(1, 0);
10986 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10987 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10989 case TEXTURELAYERTYPE_FOG:
10990 // singletexture fogging
10991 if (layer->texture)
10993 R_Mesh_TexBind(0, layer->texture);
10994 R_Mesh_TexMatrix(0, &layer->texmatrix);
10995 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10996 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11000 R_Mesh_TexBind(0, 0);
11001 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11003 R_Mesh_TexBind(1, 0);
11004 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11005 // generate a color array for the fog pass
11006 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[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_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11023 // OpenGL 1.1 - crusty old voodoo path
11026 const texturelayer_t *layer;
11027 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);
11028 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11030 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11032 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11034 if (layerindex == 0)
11035 GL_AlphaTest(true);
11038 GL_AlphaTest(false);
11039 GL_DepthFunc(GL_EQUAL);
11042 GL_DepthMask(layer->depthmask && writedepth);
11043 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11044 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11045 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11046 switch (layer->type)
11048 case TEXTURELAYERTYPE_LITTEXTURE:
11049 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
11051 // two-pass lit texture with 2x rgbscale
11052 // first the lightmap pass
11053 R_Mesh_TexBind(0, r_texture_white);
11054 R_Mesh_TexMatrix(0, NULL);
11055 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11056 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11057 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11058 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11059 else if (FAKELIGHT_ENABLED)
11060 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
11061 else if (rsurface.uselightmaptexture)
11062 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11064 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11065 // then apply the texture to it
11066 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11067 R_Mesh_TexBind(0, layer->texture);
11068 R_Mesh_TexMatrix(0, &layer->texmatrix);
11069 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11070 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11071 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);
11075 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11076 R_Mesh_TexBind(0, layer->texture);
11077 R_Mesh_TexMatrix(0, &layer->texmatrix);
11078 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11079 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11080 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11081 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);
11082 else if (FAKELIGHT_ENABLED)
11083 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);
11085 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);
11088 case TEXTURELAYERTYPE_TEXTURE:
11089 // singletexture unlit texture with transparency support
11090 R_Mesh_TexBind(0, layer->texture);
11091 R_Mesh_TexMatrix(0, &layer->texmatrix);
11092 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11093 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11094 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);
11096 case TEXTURELAYERTYPE_FOG:
11097 // singletexture fogging
11098 if (layer->texture)
11100 R_Mesh_TexBind(0, layer->texture);
11101 R_Mesh_TexMatrix(0, &layer->texmatrix);
11102 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11103 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11107 R_Mesh_TexBind(0, 0);
11108 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11110 // generate a color array for the fog pass
11111 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11112 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11116 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11119 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11121 GL_DepthFunc(GL_LEQUAL);
11122 GL_AlphaTest(false);
11126 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11130 r_vertexgeneric_t *batchvertex;
11133 // R_Mesh_ResetTextureState();
11134 R_SetupShader_Generic_NoTexture(false, false);
11136 if(rsurface.texture && rsurface.texture->currentskinframe)
11138 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11139 c[3] *= rsurface.texture->currentalpha;
11149 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11151 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11152 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11153 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11156 // brighten it up (as texture value 127 means "unlit")
11157 c[0] *= 2 * r_refdef.view.colorscale;
11158 c[1] *= 2 * r_refdef.view.colorscale;
11159 c[2] *= 2 * r_refdef.view.colorscale;
11161 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11162 c[3] *= r_wateralpha.value;
11164 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11166 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11167 GL_DepthMask(false);
11169 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11171 GL_BlendFunc(GL_ONE, GL_ONE);
11172 GL_DepthMask(false);
11174 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11176 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11177 GL_DepthMask(false);
11179 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11181 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11182 GL_DepthMask(false);
11186 GL_BlendFunc(GL_ONE, GL_ZERO);
11187 GL_DepthMask(writedepth);
11190 if (r_showsurfaces.integer == 3)
11192 rsurface.passcolor4f = NULL;
11194 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11196 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11198 rsurface.passcolor4f = NULL;
11199 rsurface.passcolor4f_vertexbuffer = 0;
11200 rsurface.passcolor4f_bufferoffset = 0;
11202 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11204 qboolean applycolor = true;
11207 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11209 r_refdef.lightmapintensity = 1;
11210 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11211 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11213 else if (FAKELIGHT_ENABLED)
11215 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11217 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11218 RSurf_DrawBatch_GL11_ApplyFakeLight();
11219 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11223 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11225 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11226 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11227 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11230 if(!rsurface.passcolor4f)
11231 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11233 RSurf_DrawBatch_GL11_ApplyAmbient();
11234 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11235 if(r_refdef.fogenabled)
11236 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11237 RSurf_DrawBatch_GL11_ClampColor();
11239 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11240 R_SetupShader_Generic_NoTexture(false, false);
11243 else if (!r_refdef.view.showdebug)
11245 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11246 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11247 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11249 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11250 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11252 R_Mesh_PrepareVertices_Generic_Unlock();
11255 else if (r_showsurfaces.integer == 4)
11257 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11258 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11259 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11261 unsigned char d = (vi << 3) * (1.0f / 256.0f);
11262 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11263 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11265 R_Mesh_PrepareVertices_Generic_Unlock();
11268 else if (r_showsurfaces.integer == 2)
11271 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11272 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11273 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11275 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11276 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11277 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11278 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11279 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11280 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11281 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11283 R_Mesh_PrepareVertices_Generic_Unlock();
11284 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11288 int texturesurfaceindex;
11290 const msurface_t *surface;
11291 float surfacecolor4f[4];
11292 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11293 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11295 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11297 surface = texturesurfacelist[texturesurfaceindex];
11298 k = (int)(((size_t)surface) / sizeof(msurface_t));
11299 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11300 for (j = 0;j < surface->num_vertices;j++)
11302 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11303 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11307 R_Mesh_PrepareVertices_Generic_Unlock();
11312 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11315 RSurf_SetupDepthAndCulling();
11316 if (r_showsurfaces.integer)
11318 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11321 switch (vid.renderpath)
11323 case RENDERPATH_GL20:
11324 case RENDERPATH_D3D9:
11325 case RENDERPATH_D3D10:
11326 case RENDERPATH_D3D11:
11327 case RENDERPATH_SOFT:
11328 case RENDERPATH_GLES2:
11329 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11331 case RENDERPATH_GL13:
11332 case RENDERPATH_GLES1:
11333 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11335 case RENDERPATH_GL11:
11336 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11342 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11345 RSurf_SetupDepthAndCulling();
11346 if (r_showsurfaces.integer)
11348 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11351 switch (vid.renderpath)
11353 case RENDERPATH_GL20:
11354 case RENDERPATH_D3D9:
11355 case RENDERPATH_D3D10:
11356 case RENDERPATH_D3D11:
11357 case RENDERPATH_SOFT:
11358 case RENDERPATH_GLES2:
11359 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11361 case RENDERPATH_GL13:
11362 case RENDERPATH_GLES1:
11363 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11365 case RENDERPATH_GL11:
11366 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11372 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11375 int texturenumsurfaces, endsurface;
11376 texture_t *texture;
11377 const msurface_t *surface;
11378 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11380 // if the model is static it doesn't matter what value we give for
11381 // wantnormals and wanttangents, so this logic uses only rules applicable
11382 // to a model, knowing that they are meaningless otherwise
11383 if (ent == r_refdef.scene.worldentity)
11384 RSurf_ActiveWorldEntity();
11385 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11386 RSurf_ActiveModelEntity(ent, false, false, false);
11389 switch (vid.renderpath)
11391 case RENDERPATH_GL20:
11392 case RENDERPATH_D3D9:
11393 case RENDERPATH_D3D10:
11394 case RENDERPATH_D3D11:
11395 case RENDERPATH_SOFT:
11396 case RENDERPATH_GLES2:
11397 RSurf_ActiveModelEntity(ent, true, true, false);
11399 case RENDERPATH_GL11:
11400 case RENDERPATH_GL13:
11401 case RENDERPATH_GLES1:
11402 RSurf_ActiveModelEntity(ent, true, false, false);
11407 if (r_transparentdepthmasking.integer)
11409 qboolean setup = false;
11410 for (i = 0;i < numsurfaces;i = j)
11413 surface = rsurface.modelsurfaces + surfacelist[i];
11414 texture = surface->texture;
11415 rsurface.texture = R_GetCurrentTexture(texture);
11416 rsurface.lightmaptexture = NULL;
11417 rsurface.deluxemaptexture = NULL;
11418 rsurface.uselightmaptexture = false;
11419 // scan ahead until we find a different texture
11420 endsurface = min(i + 1024, numsurfaces);
11421 texturenumsurfaces = 0;
11422 texturesurfacelist[texturenumsurfaces++] = surface;
11423 for (;j < endsurface;j++)
11425 surface = rsurface.modelsurfaces + surfacelist[j];
11426 if (texture != surface->texture)
11428 texturesurfacelist[texturenumsurfaces++] = surface;
11430 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11432 // render the range of surfaces as depth
11436 GL_ColorMask(0,0,0,0);
11438 GL_DepthTest(true);
11439 GL_BlendFunc(GL_ONE, GL_ZERO);
11440 GL_DepthMask(true);
11441 // R_Mesh_ResetTextureState();
11443 RSurf_SetupDepthAndCulling();
11444 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11445 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11446 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11450 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11453 for (i = 0;i < numsurfaces;i = j)
11456 surface = rsurface.modelsurfaces + surfacelist[i];
11457 texture = surface->texture;
11458 rsurface.texture = R_GetCurrentTexture(texture);
11459 // scan ahead until we find a different texture
11460 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11461 texturenumsurfaces = 0;
11462 texturesurfacelist[texturenumsurfaces++] = surface;
11463 if(FAKELIGHT_ENABLED)
11465 rsurface.lightmaptexture = NULL;
11466 rsurface.deluxemaptexture = NULL;
11467 rsurface.uselightmaptexture = false;
11468 for (;j < endsurface;j++)
11470 surface = rsurface.modelsurfaces + surfacelist[j];
11471 if (texture != surface->texture)
11473 texturesurfacelist[texturenumsurfaces++] = surface;
11478 rsurface.lightmaptexture = surface->lightmaptexture;
11479 rsurface.deluxemaptexture = surface->deluxemaptexture;
11480 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11481 for (;j < endsurface;j++)
11483 surface = rsurface.modelsurfaces + surfacelist[j];
11484 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11486 texturesurfacelist[texturenumsurfaces++] = surface;
11489 // render the range of surfaces
11490 if (ent == r_refdef.scene.worldentity)
11491 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11493 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11495 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11498 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11500 // transparent surfaces get pushed off into the transparent queue
11501 int surfacelistindex;
11502 const msurface_t *surface;
11503 vec3_t tempcenter, center;
11504 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11506 surface = texturesurfacelist[surfacelistindex];
11507 if (r_transparent_sortsurfacesbynearest.integer)
11509 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11510 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11511 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11515 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11516 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11517 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11519 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11520 if (rsurface.entity->transparent_offset) // transparent offset
11522 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11523 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11524 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11526 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);
11530 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11532 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11534 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11536 RSurf_SetupDepthAndCulling();
11537 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11538 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11539 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11543 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11547 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11550 if (!rsurface.texture->currentnumlayers)
11552 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11553 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11555 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11557 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11558 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11559 else if (!rsurface.texture->currentnumlayers)
11561 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11563 // in the deferred case, transparent surfaces were queued during prepass
11564 if (!r_shadow_usingdeferredprepass)
11565 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11569 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11570 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11575 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11578 texture_t *texture;
11579 R_FrameData_SetMark();
11580 // break the surface list down into batches by texture and use of lightmapping
11581 for (i = 0;i < numsurfaces;i = j)
11584 // texture is the base texture pointer, rsurface.texture is the
11585 // current frame/skin the texture is directing us to use (for example
11586 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11587 // use skin 1 instead)
11588 texture = surfacelist[i]->texture;
11589 rsurface.texture = R_GetCurrentTexture(texture);
11590 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11592 // if this texture is not the kind we want, skip ahead to the next one
11593 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11597 if(FAKELIGHT_ENABLED || depthonly || prepass)
11599 rsurface.lightmaptexture = NULL;
11600 rsurface.deluxemaptexture = NULL;
11601 rsurface.uselightmaptexture = false;
11602 // simply scan ahead until we find a different texture or lightmap state
11603 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11608 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11609 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11610 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11611 // simply scan ahead until we find a different texture or lightmap state
11612 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11615 // render the range of surfaces
11616 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11618 R_FrameData_ReturnToMark();
11621 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11625 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11628 if (!rsurface.texture->currentnumlayers)
11630 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11631 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11633 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11635 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11636 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11637 else if (!rsurface.texture->currentnumlayers)
11639 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11641 // in the deferred case, transparent surfaces were queued during prepass
11642 if (!r_shadow_usingdeferredprepass)
11643 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11647 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11648 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11653 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11656 texture_t *texture;
11657 R_FrameData_SetMark();
11658 // break the surface list down into batches by texture and use of lightmapping
11659 for (i = 0;i < numsurfaces;i = j)
11662 // texture is the base texture pointer, rsurface.texture is the
11663 // current frame/skin the texture is directing us to use (for example
11664 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11665 // use skin 1 instead)
11666 texture = surfacelist[i]->texture;
11667 rsurface.texture = R_GetCurrentTexture(texture);
11668 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11670 // if this texture is not the kind we want, skip ahead to the next one
11671 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11675 if(FAKELIGHT_ENABLED || depthonly || prepass)
11677 rsurface.lightmaptexture = NULL;
11678 rsurface.deluxemaptexture = NULL;
11679 rsurface.uselightmaptexture = false;
11680 // simply scan ahead until we find a different texture or lightmap state
11681 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11686 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11687 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11688 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11689 // simply scan ahead until we find a different texture or lightmap state
11690 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11693 // render the range of surfaces
11694 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11696 R_FrameData_ReturnToMark();
11699 float locboxvertex3f[6*4*3] =
11701 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11702 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11703 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11704 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11705 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11706 1,0,0, 0,0,0, 0,1,0, 1,1,0
11709 unsigned short locboxelements[6*2*3] =
11714 12,13,14, 12,14,15,
11715 16,17,18, 16,18,19,
11719 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11722 cl_locnode_t *loc = (cl_locnode_t *)ent;
11724 float vertex3f[6*4*3];
11726 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11727 GL_DepthMask(false);
11728 GL_DepthRange(0, 1);
11729 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11730 GL_DepthTest(true);
11731 GL_CullFace(GL_NONE);
11732 R_EntityMatrix(&identitymatrix);
11734 // R_Mesh_ResetTextureState();
11736 i = surfacelist[0];
11737 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11738 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11739 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11740 surfacelist[0] < 0 ? 0.5f : 0.125f);
11742 if (VectorCompare(loc->mins, loc->maxs))
11744 VectorSet(size, 2, 2, 2);
11745 VectorMA(loc->mins, -0.5f, size, mins);
11749 VectorCopy(loc->mins, mins);
11750 VectorSubtract(loc->maxs, loc->mins, size);
11753 for (i = 0;i < 6*4*3;)
11754 for (j = 0;j < 3;j++, i++)
11755 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11757 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11758 R_SetupShader_Generic_NoTexture(false, false);
11759 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11762 void R_DrawLocs(void)
11765 cl_locnode_t *loc, *nearestloc;
11767 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11768 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11770 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11771 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11775 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11777 if (decalsystem->decals)
11778 Mem_Free(decalsystem->decals);
11779 memset(decalsystem, 0, sizeof(*decalsystem));
11782 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)
11785 tridecal_t *decals;
11788 // expand or initialize the system
11789 if (decalsystem->maxdecals <= decalsystem->numdecals)
11791 decalsystem_t old = *decalsystem;
11792 qboolean useshortelements;
11793 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11794 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11795 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)));
11796 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11797 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11798 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11799 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11800 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11801 if (decalsystem->numdecals)
11802 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11804 Mem_Free(old.decals);
11805 for (i = 0;i < decalsystem->maxdecals*3;i++)
11806 decalsystem->element3i[i] = i;
11807 if (useshortelements)
11808 for (i = 0;i < decalsystem->maxdecals*3;i++)
11809 decalsystem->element3s[i] = i;
11812 // grab a decal and search for another free slot for the next one
11813 decals = decalsystem->decals;
11814 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11815 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11817 decalsystem->freedecal = i;
11818 if (decalsystem->numdecals <= i)
11819 decalsystem->numdecals = i + 1;
11821 // initialize the decal
11823 decal->triangleindex = triangleindex;
11824 decal->surfaceindex = surfaceindex;
11825 decal->decalsequence = decalsequence;
11826 decal->color4f[0][0] = c0[0];
11827 decal->color4f[0][1] = c0[1];
11828 decal->color4f[0][2] = c0[2];
11829 decal->color4f[0][3] = 1;
11830 decal->color4f[1][0] = c1[0];
11831 decal->color4f[1][1] = c1[1];
11832 decal->color4f[1][2] = c1[2];
11833 decal->color4f[1][3] = 1;
11834 decal->color4f[2][0] = c2[0];
11835 decal->color4f[2][1] = c2[1];
11836 decal->color4f[2][2] = c2[2];
11837 decal->color4f[2][3] = 1;
11838 decal->vertex3f[0][0] = v0[0];
11839 decal->vertex3f[0][1] = v0[1];
11840 decal->vertex3f[0][2] = v0[2];
11841 decal->vertex3f[1][0] = v1[0];
11842 decal->vertex3f[1][1] = v1[1];
11843 decal->vertex3f[1][2] = v1[2];
11844 decal->vertex3f[2][0] = v2[0];
11845 decal->vertex3f[2][1] = v2[1];
11846 decal->vertex3f[2][2] = v2[2];
11847 decal->texcoord2f[0][0] = t0[0];
11848 decal->texcoord2f[0][1] = t0[1];
11849 decal->texcoord2f[1][0] = t1[0];
11850 decal->texcoord2f[1][1] = t1[1];
11851 decal->texcoord2f[2][0] = t2[0];
11852 decal->texcoord2f[2][1] = t2[1];
11853 TriangleNormal(v0, v1, v2, decal->plane);
11854 VectorNormalize(decal->plane);
11855 decal->plane[3] = DotProduct(v0, decal->plane);
11858 extern cvar_t cl_decals_bias;
11859 extern cvar_t cl_decals_models;
11860 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11861 // baseparms, parms, temps
11862 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)
11867 const float *vertex3f;
11868 const float *normal3f;
11870 float points[2][9][3];
11877 e = rsurface.modelelement3i + 3*triangleindex;
11879 vertex3f = rsurface.modelvertex3f;
11880 normal3f = rsurface.modelnormal3f;
11884 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11886 index = 3*e[cornerindex];
11887 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11892 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11894 index = 3*e[cornerindex];
11895 VectorCopy(vertex3f + index, v[cornerindex]);
11900 //TriangleNormal(v[0], v[1], v[2], normal);
11901 //if (DotProduct(normal, localnormal) < 0.0f)
11903 // clip by each of the box planes formed from the projection matrix
11904 // if anything survives, we emit the decal
11905 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]);
11908 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]);
11911 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]);
11914 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]);
11917 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]);
11920 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]);
11923 // some part of the triangle survived, so we have to accept it...
11926 // dynamic always uses the original triangle
11928 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11930 index = 3*e[cornerindex];
11931 VectorCopy(vertex3f + index, v[cornerindex]);
11934 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11936 // convert vertex positions to texcoords
11937 Matrix4x4_Transform(projection, v[cornerindex], temp);
11938 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11939 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11940 // calculate distance fade from the projection origin
11941 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11942 f = bound(0.0f, f, 1.0f);
11943 c[cornerindex][0] = r * f;
11944 c[cornerindex][1] = g * f;
11945 c[cornerindex][2] = b * f;
11946 c[cornerindex][3] = 1.0f;
11947 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11950 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);
11952 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11953 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);
11955 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)
11957 matrix4x4_t projection;
11958 decalsystem_t *decalsystem;
11961 const msurface_t *surface;
11962 const msurface_t *surfaces;
11963 const int *surfacelist;
11964 const texture_t *texture;
11966 int numsurfacelist;
11967 int surfacelistindex;
11970 float localorigin[3];
11971 float localnormal[3];
11972 float localmins[3];
11973 float localmaxs[3];
11976 float planes[6][4];
11979 int bih_triangles_count;
11980 int bih_triangles[256];
11981 int bih_surfaces[256];
11983 decalsystem = &ent->decalsystem;
11984 model = ent->model;
11985 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11987 R_DecalSystem_Reset(&ent->decalsystem);
11991 if (!model->brush.data_leafs && !cl_decals_models.integer)
11993 if (decalsystem->model)
11994 R_DecalSystem_Reset(decalsystem);
11998 if (decalsystem->model != model)
11999 R_DecalSystem_Reset(decalsystem);
12000 decalsystem->model = model;
12002 RSurf_ActiveModelEntity(ent, true, false, false);
12004 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12005 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12006 VectorNormalize(localnormal);
12007 localsize = worldsize*rsurface.inversematrixscale;
12008 localmins[0] = localorigin[0] - localsize;
12009 localmins[1] = localorigin[1] - localsize;
12010 localmins[2] = localorigin[2] - localsize;
12011 localmaxs[0] = localorigin[0] + localsize;
12012 localmaxs[1] = localorigin[1] + localsize;
12013 localmaxs[2] = localorigin[2] + localsize;
12015 //VectorCopy(localnormal, planes[4]);
12016 //VectorVectors(planes[4], planes[2], planes[0]);
12017 AnglesFromVectors(angles, localnormal, NULL, false);
12018 AngleVectors(angles, planes[0], planes[2], planes[4]);
12019 VectorNegate(planes[0], planes[1]);
12020 VectorNegate(planes[2], planes[3]);
12021 VectorNegate(planes[4], planes[5]);
12022 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12023 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12024 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12025 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12026 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12027 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12032 matrix4x4_t forwardprojection;
12033 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12034 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12039 float projectionvector[4][3];
12040 VectorScale(planes[0], ilocalsize, projectionvector[0]);
12041 VectorScale(planes[2], ilocalsize, projectionvector[1]);
12042 VectorScale(planes[4], ilocalsize, projectionvector[2]);
12043 projectionvector[0][0] = planes[0][0] * ilocalsize;
12044 projectionvector[0][1] = planes[1][0] * ilocalsize;
12045 projectionvector[0][2] = planes[2][0] * ilocalsize;
12046 projectionvector[1][0] = planes[0][1] * ilocalsize;
12047 projectionvector[1][1] = planes[1][1] * ilocalsize;
12048 projectionvector[1][2] = planes[2][1] * ilocalsize;
12049 projectionvector[2][0] = planes[0][2] * ilocalsize;
12050 projectionvector[2][1] = planes[1][2] * ilocalsize;
12051 projectionvector[2][2] = planes[2][2] * ilocalsize;
12052 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12053 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12054 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12055 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12059 dynamic = model->surfmesh.isanimated;
12060 numsurfacelist = model->nummodelsurfaces;
12061 surfacelist = model->sortedmodelsurfaces;
12062 surfaces = model->data_surfaces;
12065 bih_triangles_count = -1;
12068 if(model->render_bih.numleafs)
12069 bih = &model->render_bih;
12070 else if(model->collision_bih.numleafs)
12071 bih = &model->collision_bih;
12074 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12075 if(bih_triangles_count == 0)
12077 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12079 if(bih_triangles_count > 0)
12081 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12083 surfaceindex = bih_surfaces[triangleindex];
12084 surface = surfaces + surfaceindex;
12085 texture = surface->texture;
12086 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12088 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12090 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12095 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12097 surfaceindex = surfacelist[surfacelistindex];
12098 surface = surfaces + surfaceindex;
12099 // check cull box first because it rejects more than any other check
12100 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12102 // skip transparent surfaces
12103 texture = surface->texture;
12104 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12106 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12108 numtriangles = surface->num_triangles;
12109 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12110 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12115 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12116 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)
12118 int renderentityindex;
12119 float worldmins[3];
12120 float worldmaxs[3];
12121 entity_render_t *ent;
12123 if (!cl_decals_newsystem.integer)
12126 worldmins[0] = worldorigin[0] - worldsize;
12127 worldmins[1] = worldorigin[1] - worldsize;
12128 worldmins[2] = worldorigin[2] - worldsize;
12129 worldmaxs[0] = worldorigin[0] + worldsize;
12130 worldmaxs[1] = worldorigin[1] + worldsize;
12131 worldmaxs[2] = worldorigin[2] + worldsize;
12133 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12135 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12137 ent = r_refdef.scene.entities[renderentityindex];
12138 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12141 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12145 typedef struct r_decalsystem_splatqueue_s
12147 vec3_t worldorigin;
12148 vec3_t worldnormal;
12152 unsigned int decalsequence;
12154 r_decalsystem_splatqueue_t;
12156 int r_decalsystem_numqueued = 0;
12157 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12159 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)
12161 r_decalsystem_splatqueue_t *queue;
12163 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12166 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12167 VectorCopy(worldorigin, queue->worldorigin);
12168 VectorCopy(worldnormal, queue->worldnormal);
12169 Vector4Set(queue->color, r, g, b, a);
12170 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12171 queue->worldsize = worldsize;
12172 queue->decalsequence = cl.decalsequence++;
12175 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12178 r_decalsystem_splatqueue_t *queue;
12180 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12181 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);
12182 r_decalsystem_numqueued = 0;
12185 extern cvar_t cl_decals_max;
12186 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12189 decalsystem_t *decalsystem = &ent->decalsystem;
12191 unsigned int killsequence;
12196 if (!decalsystem->numdecals)
12199 if (r_showsurfaces.integer)
12202 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12204 R_DecalSystem_Reset(decalsystem);
12208 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12209 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12211 if (decalsystem->lastupdatetime)
12212 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12215 decalsystem->lastupdatetime = r_refdef.scene.time;
12216 numdecals = decalsystem->numdecals;
12218 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12220 if (decal->color4f[0][3])
12222 decal->lived += frametime;
12223 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12225 memset(decal, 0, sizeof(*decal));
12226 if (decalsystem->freedecal > i)
12227 decalsystem->freedecal = i;
12231 decal = decalsystem->decals;
12232 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12235 // collapse the array by shuffling the tail decals into the gaps
12238 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12239 decalsystem->freedecal++;
12240 if (decalsystem->freedecal == numdecals)
12242 decal[decalsystem->freedecal] = decal[--numdecals];
12245 decalsystem->numdecals = numdecals;
12247 if (numdecals <= 0)
12249 // if there are no decals left, reset decalsystem
12250 R_DecalSystem_Reset(decalsystem);
12254 extern skinframe_t *decalskinframe;
12255 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12258 decalsystem_t *decalsystem = &ent->decalsystem;
12267 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12270 numdecals = decalsystem->numdecals;
12274 if (r_showsurfaces.integer)
12277 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12279 R_DecalSystem_Reset(decalsystem);
12283 // if the model is static it doesn't matter what value we give for
12284 // wantnormals and wanttangents, so this logic uses only rules applicable
12285 // to a model, knowing that they are meaningless otherwise
12286 if (ent == r_refdef.scene.worldentity)
12287 RSurf_ActiveWorldEntity();
12289 RSurf_ActiveModelEntity(ent, false, false, false);
12291 decalsystem->lastupdatetime = r_refdef.scene.time;
12293 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12295 // update vertex positions for animated models
12296 v3f = decalsystem->vertex3f;
12297 c4f = decalsystem->color4f;
12298 t2f = decalsystem->texcoord2f;
12299 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12301 if (!decal->color4f[0][3])
12304 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12308 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12311 // update color values for fading decals
12312 if (decal->lived >= cl_decals_time.value)
12313 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12317 c4f[ 0] = decal->color4f[0][0] * alpha;
12318 c4f[ 1] = decal->color4f[0][1] * alpha;
12319 c4f[ 2] = decal->color4f[0][2] * alpha;
12321 c4f[ 4] = decal->color4f[1][0] * alpha;
12322 c4f[ 5] = decal->color4f[1][1] * alpha;
12323 c4f[ 6] = decal->color4f[1][2] * alpha;
12325 c4f[ 8] = decal->color4f[2][0] * alpha;
12326 c4f[ 9] = decal->color4f[2][1] * alpha;
12327 c4f[10] = decal->color4f[2][2] * alpha;
12330 t2f[0] = decal->texcoord2f[0][0];
12331 t2f[1] = decal->texcoord2f[0][1];
12332 t2f[2] = decal->texcoord2f[1][0];
12333 t2f[3] = decal->texcoord2f[1][1];
12334 t2f[4] = decal->texcoord2f[2][0];
12335 t2f[5] = decal->texcoord2f[2][1];
12337 // update vertex positions for animated models
12338 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12340 e = rsurface.modelelement3i + 3*decal->triangleindex;
12341 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12342 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12343 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12347 VectorCopy(decal->vertex3f[0], v3f);
12348 VectorCopy(decal->vertex3f[1], v3f + 3);
12349 VectorCopy(decal->vertex3f[2], v3f + 6);
12352 if (r_refdef.fogenabled)
12354 alpha = RSurf_FogVertex(v3f);
12355 VectorScale(c4f, alpha, c4f);
12356 alpha = RSurf_FogVertex(v3f + 3);
12357 VectorScale(c4f + 4, alpha, c4f + 4);
12358 alpha = RSurf_FogVertex(v3f + 6);
12359 VectorScale(c4f + 8, alpha, c4f + 8);
12370 r_refdef.stats[r_stat_drawndecals] += numtris;
12372 // now render the decals all at once
12373 // (this assumes they all use one particle font texture!)
12374 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);
12375 // R_Mesh_ResetTextureState();
12376 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12377 GL_DepthMask(false);
12378 GL_DepthRange(0, 1);
12379 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12380 GL_DepthTest(true);
12381 GL_CullFace(GL_NONE);
12382 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12383 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12384 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12388 static void R_DrawModelDecals(void)
12392 // fade faster when there are too many decals
12393 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12394 for (i = 0;i < r_refdef.scene.numentities;i++)
12395 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12397 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12398 for (i = 0;i < r_refdef.scene.numentities;i++)
12399 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12400 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12402 R_DecalSystem_ApplySplatEntitiesQueue();
12404 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12405 for (i = 0;i < r_refdef.scene.numentities;i++)
12406 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12408 r_refdef.stats[r_stat_totaldecals] += numdecals;
12410 if (r_showsurfaces.integer)
12413 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12415 for (i = 0;i < r_refdef.scene.numentities;i++)
12417 if (!r_refdef.viewcache.entityvisible[i])
12419 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12420 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12424 extern cvar_t mod_collision_bih;
12425 static void R_DrawDebugModel(void)
12427 entity_render_t *ent = rsurface.entity;
12428 int i, j, flagsmask;
12429 const msurface_t *surface;
12430 dp_model_t *model = ent->model;
12432 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12435 if (r_showoverdraw.value > 0)
12437 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12438 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12439 R_SetupShader_Generic_NoTexture(false, false);
12440 GL_DepthTest(false);
12441 GL_DepthMask(false);
12442 GL_DepthRange(0, 1);
12443 GL_BlendFunc(GL_ONE, GL_ONE);
12444 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12446 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12448 rsurface.texture = R_GetCurrentTexture(surface->texture);
12449 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12451 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12452 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12453 if (!rsurface.texture->currentlayers->depthmask)
12454 GL_Color(c, 0, 0, 1.0f);
12455 else if (ent == r_refdef.scene.worldentity)
12456 GL_Color(c, c, c, 1.0f);
12458 GL_Color(0, c, 0, 1.0f);
12459 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12463 rsurface.texture = NULL;
12466 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12468 // R_Mesh_ResetTextureState();
12469 R_SetupShader_Generic_NoTexture(false, false);
12470 GL_DepthRange(0, 1);
12471 GL_DepthTest(!r_showdisabledepthtest.integer);
12472 GL_DepthMask(false);
12473 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12475 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12479 qboolean cullbox = false;
12480 const q3mbrush_t *brush;
12481 const bih_t *bih = &model->collision_bih;
12482 const bih_leaf_t *bihleaf;
12483 float vertex3f[3][3];
12484 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12485 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12487 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12489 switch (bihleaf->type)
12492 brush = model->brush.data_brushes + bihleaf->itemindex;
12493 if (brush->colbrushf && brush->colbrushf->numtriangles)
12495 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);
12496 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12497 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12500 case BIH_COLLISIONTRIANGLE:
12501 triangleindex = bihleaf->itemindex;
12502 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12503 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12504 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12505 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);
12506 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12507 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12509 case BIH_RENDERTRIANGLE:
12510 triangleindex = bihleaf->itemindex;
12511 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12512 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12513 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12514 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);
12515 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12516 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12522 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12525 if (r_showtris.integer && qglPolygonMode)
12527 if (r_showdisabledepthtest.integer)
12529 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12530 GL_DepthMask(false);
12534 GL_BlendFunc(GL_ONE, GL_ZERO);
12535 GL_DepthMask(true);
12537 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12538 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12540 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12542 rsurface.texture = R_GetCurrentTexture(surface->texture);
12543 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12545 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12546 if (!rsurface.texture->currentlayers->depthmask)
12547 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12548 else if (ent == r_refdef.scene.worldentity)
12549 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12551 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12552 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12556 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12557 rsurface.texture = NULL;
12560 if (r_shownormals.value != 0 && qglBegin)
12564 if (r_showdisabledepthtest.integer)
12566 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12567 GL_DepthMask(false);
12571 GL_BlendFunc(GL_ONE, GL_ZERO);
12572 GL_DepthMask(true);
12574 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12576 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12578 rsurface.texture = R_GetCurrentTexture(surface->texture);
12579 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12581 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12582 qglBegin(GL_LINES);
12583 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12585 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12587 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12588 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12589 qglVertex3f(v[0], v[1], v[2]);
12590 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12591 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12592 qglVertex3f(v[0], v[1], v[2]);
12595 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12597 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12599 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12600 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12601 qglVertex3f(v[0], v[1], v[2]);
12602 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12603 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12604 qglVertex3f(v[0], v[1], v[2]);
12607 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12609 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12611 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12612 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12613 qglVertex3f(v[0], v[1], v[2]);
12614 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12615 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12616 qglVertex3f(v[0], v[1], v[2]);
12619 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12621 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12623 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12624 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12625 qglVertex3f(v[0], v[1], v[2]);
12626 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12627 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12628 qglVertex3f(v[0], v[1], v[2]);
12635 rsurface.texture = NULL;
12640 int r_maxsurfacelist = 0;
12641 const msurface_t **r_surfacelist = NULL;
12642 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12644 int i, j, endj, flagsmask;
12645 dp_model_t *model = r_refdef.scene.worldmodel;
12646 msurface_t *surfaces;
12647 unsigned char *update;
12648 int numsurfacelist = 0;
12652 if (r_maxsurfacelist < model->num_surfaces)
12654 r_maxsurfacelist = model->num_surfaces;
12656 Mem_Free((msurface_t**)r_surfacelist);
12657 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12660 RSurf_ActiveWorldEntity();
12662 surfaces = model->data_surfaces;
12663 update = model->brushq1.lightmapupdateflags;
12665 // update light styles on this submodel
12666 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12668 model_brush_lightstyleinfo_t *style;
12669 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12671 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12673 int *list = style->surfacelist;
12674 style->value = r_refdef.scene.lightstylevalue[style->style];
12675 for (j = 0;j < style->numsurfaces;j++)
12676 update[list[j]] = true;
12681 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12685 R_DrawDebugModel();
12686 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12690 rsurface.lightmaptexture = NULL;
12691 rsurface.deluxemaptexture = NULL;
12692 rsurface.uselightmaptexture = false;
12693 rsurface.texture = NULL;
12694 rsurface.rtlight = NULL;
12695 numsurfacelist = 0;
12696 // add visible surfaces to draw list
12697 for (i = 0;i < model->nummodelsurfaces;i++)
12699 j = model->sortedmodelsurfaces[i];
12700 if (r_refdef.viewcache.world_surfacevisible[j])
12701 r_surfacelist[numsurfacelist++] = surfaces + j;
12703 // update lightmaps if needed
12704 if (model->brushq1.firstrender)
12706 model->brushq1.firstrender = false;
12707 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12709 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12713 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12714 if (r_refdef.viewcache.world_surfacevisible[j])
12716 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12718 // don't do anything if there were no surfaces
12719 if (!numsurfacelist)
12721 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12724 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12726 // add to stats if desired
12727 if (r_speeds.integer && !skysurfaces && !depthonly)
12729 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12730 for (j = 0;j < numsurfacelist;j++)
12731 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12734 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12737 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12739 int i, j, endj, flagsmask;
12740 dp_model_t *model = ent->model;
12741 msurface_t *surfaces;
12742 unsigned char *update;
12743 int numsurfacelist = 0;
12747 if (r_maxsurfacelist < model->num_surfaces)
12749 r_maxsurfacelist = model->num_surfaces;
12751 Mem_Free((msurface_t **)r_surfacelist);
12752 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12755 // if the model is static it doesn't matter what value we give for
12756 // wantnormals and wanttangents, so this logic uses only rules applicable
12757 // to a model, knowing that they are meaningless otherwise
12758 if (ent == r_refdef.scene.worldentity)
12759 RSurf_ActiveWorldEntity();
12760 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12761 RSurf_ActiveModelEntity(ent, false, false, false);
12763 RSurf_ActiveModelEntity(ent, true, true, true);
12764 else if (depthonly)
12766 switch (vid.renderpath)
12768 case RENDERPATH_GL20:
12769 case RENDERPATH_D3D9:
12770 case RENDERPATH_D3D10:
12771 case RENDERPATH_D3D11:
12772 case RENDERPATH_SOFT:
12773 case RENDERPATH_GLES2:
12774 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12776 case RENDERPATH_GL11:
12777 case RENDERPATH_GL13:
12778 case RENDERPATH_GLES1:
12779 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12785 switch (vid.renderpath)
12787 case RENDERPATH_GL20:
12788 case RENDERPATH_D3D9:
12789 case RENDERPATH_D3D10:
12790 case RENDERPATH_D3D11:
12791 case RENDERPATH_SOFT:
12792 case RENDERPATH_GLES2:
12793 RSurf_ActiveModelEntity(ent, true, true, false);
12795 case RENDERPATH_GL11:
12796 case RENDERPATH_GL13:
12797 case RENDERPATH_GLES1:
12798 RSurf_ActiveModelEntity(ent, true, false, false);
12803 surfaces = model->data_surfaces;
12804 update = model->brushq1.lightmapupdateflags;
12806 // update light styles
12807 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12809 model_brush_lightstyleinfo_t *style;
12810 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12812 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12814 int *list = style->surfacelist;
12815 style->value = r_refdef.scene.lightstylevalue[style->style];
12816 for (j = 0;j < style->numsurfaces;j++)
12817 update[list[j]] = true;
12822 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12826 R_DrawDebugModel();
12827 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12831 rsurface.lightmaptexture = NULL;
12832 rsurface.deluxemaptexture = NULL;
12833 rsurface.uselightmaptexture = false;
12834 rsurface.texture = NULL;
12835 rsurface.rtlight = NULL;
12836 numsurfacelist = 0;
12837 // add visible surfaces to draw list
12838 for (i = 0;i < model->nummodelsurfaces;i++)
12839 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12840 // don't do anything if there were no surfaces
12841 if (!numsurfacelist)
12843 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12846 // update lightmaps if needed
12850 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12855 R_BuildLightMap(ent, surfaces + j);
12860 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12862 // add to stats if desired
12863 if (r_speeds.integer && !skysurfaces && !depthonly)
12865 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12866 for (j = 0;j < numsurfacelist;j++)
12867 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12870 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12873 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12875 static texture_t texture;
12876 static msurface_t surface;
12877 const msurface_t *surfacelist = &surface;
12879 // fake enough texture and surface state to render this geometry
12881 texture.update_lastrenderframe = -1; // regenerate this texture
12882 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12883 texture.basealpha = 1.0f;
12884 texture.currentskinframe = skinframe;
12885 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12886 texture.offsetmapping = OFFSETMAPPING_OFF;
12887 texture.offsetscale = 1;
12888 texture.specularscalemod = 1;
12889 texture.specularpowermod = 1;
12890 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12891 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12892 // JUST GREP FOR "specularscalemod = 1".
12894 surface.texture = &texture;
12895 surface.num_triangles = numtriangles;
12896 surface.num_firsttriangle = firsttriangle;
12897 surface.num_vertices = numvertices;
12898 surface.num_firstvertex = firstvertex;
12901 rsurface.texture = R_GetCurrentTexture(surface.texture);
12902 rsurface.lightmaptexture = NULL;
12903 rsurface.deluxemaptexture = NULL;
12904 rsurface.uselightmaptexture = false;
12905 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12908 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)
12910 static msurface_t surface;
12911 const msurface_t *surfacelist = &surface;
12913 // fake enough texture and surface state to render this geometry
12914 surface.texture = texture;
12915 surface.num_triangles = numtriangles;
12916 surface.num_firsttriangle = firsttriangle;
12917 surface.num_vertices = numvertices;
12918 surface.num_firstvertex = firstvertex;
12921 rsurface.texture = R_GetCurrentTexture(surface.texture);
12922 rsurface.lightmaptexture = NULL;
12923 rsurface.deluxemaptexture = NULL;
12924 rsurface.uselightmaptexture = false;
12925 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);