2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 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)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 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"};
60 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"};
61 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"};
62 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"};
63 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"};
64 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"};
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 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"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 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)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72 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"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 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"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
82 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)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 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"};
86 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"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 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"};
89 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"};
90 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"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 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)"};
99 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)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 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."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 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."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 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"};
123 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"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 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"};
130 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
131 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
133 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
134 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
135 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
136 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
137 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
138 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
139 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
140 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
142 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)"};
143 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"};
145 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
146 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
147 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149 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"};
150 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"};
151 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
152 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
153 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"};
154 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)"};
155 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)"};
156 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
158 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)"};
159 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
160 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)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
162 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)"};
163 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)"};
164 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
165 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"};
166 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."};
167 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
177 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)"};
178 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
179 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"};
180 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
181 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
182 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
183 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"};
185 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
186 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
187 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
188 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
190 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
191 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
192 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
193 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
194 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
195 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
196 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
198 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
199 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
200 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
201 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
202 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
203 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
204 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
205 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
207 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
208 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
210 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"};
212 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"};
214 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
216 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
218 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
219 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"};
221 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."};
223 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)"};
225 extern cvar_t v_glslgamma;
226 extern cvar_t v_glslgamma_2d;
228 extern qboolean v_flipped_state;
230 static struct r_bloomstate_s
235 int bloomwidth, bloomheight;
237 textype_t texturetype;
238 int viewfbo; // used to check if r_viewfbo cvar has changed
240 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
241 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
242 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
244 int screentexturewidth, screentextureheight;
245 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
247 int bloomtexturewidth, bloomtextureheight;
248 rtexture_t *texture_bloom;
250 // arrays for rendering the screen passes
251 float screentexcoord2f[8];
252 float bloomtexcoord2f[8];
253 float offsettexcoord2f[8];
255 r_viewport_t viewport;
259 r_waterstate_t r_waterstate;
261 /// shadow volume bsp struct with automatically growing nodes buffer
264 rtexture_t *r_texture_blanknormalmap;
265 rtexture_t *r_texture_white;
266 rtexture_t *r_texture_grey128;
267 rtexture_t *r_texture_black;
268 rtexture_t *r_texture_notexture;
269 rtexture_t *r_texture_whitecube;
270 rtexture_t *r_texture_normalizationcube;
271 rtexture_t *r_texture_fogattenuation;
272 rtexture_t *r_texture_fogheighttexture;
273 rtexture_t *r_texture_gammaramps;
274 unsigned int r_texture_gammaramps_serial;
275 //rtexture_t *r_texture_fogintensity;
276 rtexture_t *r_texture_reflectcube;
278 // TODO: hash lookups?
279 typedef struct cubemapinfo_s
286 int r_texture_numcubemaps;
287 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
289 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
290 unsigned int r_numqueries;
291 unsigned int r_maxqueries;
293 typedef struct r_qwskincache_s
295 char name[MAX_QPATH];
296 skinframe_t *skinframe;
300 static r_qwskincache_t *r_qwskincache;
301 static int r_qwskincache_size;
303 /// vertex coordinates for a quad that covers the screen exactly
304 extern const float r_screenvertex3f[12];
305 extern const float r_d3dscreenvertex3f[12];
306 const float r_screenvertex3f[12] =
313 const float r_d3dscreenvertex3f[12] =
321 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
324 for (i = 0;i < verts;i++)
335 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
338 for (i = 0;i < verts;i++)
348 // FIXME: move this to client?
351 if (gamemode == GAME_NEHAHRA)
353 Cvar_Set("gl_fogenable", "0");
354 Cvar_Set("gl_fogdensity", "0.2");
355 Cvar_Set("gl_fogred", "0.3");
356 Cvar_Set("gl_foggreen", "0.3");
357 Cvar_Set("gl_fogblue", "0.3");
359 r_refdef.fog_density = 0;
360 r_refdef.fog_red = 0;
361 r_refdef.fog_green = 0;
362 r_refdef.fog_blue = 0;
363 r_refdef.fog_alpha = 1;
364 r_refdef.fog_start = 0;
365 r_refdef.fog_end = 16384;
366 r_refdef.fog_height = 1<<30;
367 r_refdef.fog_fadedepth = 128;
368 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
371 static void R_BuildBlankTextures(void)
373 unsigned char data[4];
374 data[2] = 128; // normal X
375 data[1] = 128; // normal Y
376 data[0] = 255; // normal Z
377 data[3] = 128; // height
378 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
383 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396 static void R_BuildNoTexture(void)
399 unsigned char pix[16][16][4];
400 // this makes a light grey/dark grey checkerboard texture
401 for (y = 0;y < 16;y++)
403 for (x = 0;x < 16;x++)
405 if ((y < 8) ^ (x < 8))
421 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
424 static void R_BuildWhiteCube(void)
426 unsigned char data[6*1*1*4];
427 memset(data, 255, sizeof(data));
428 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
431 static void R_BuildNormalizationCube(void)
435 vec_t s, t, intensity;
438 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
439 for (side = 0;side < 6;side++)
441 for (y = 0;y < NORMSIZE;y++)
443 for (x = 0;x < NORMSIZE;x++)
445 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
446 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
481 intensity = 127.0f / sqrt(DotProduct(v, v));
482 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
483 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
484 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
485 data[((side*64+y)*64+x)*4+3] = 255;
489 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
493 static void R_BuildFogTexture(void)
497 unsigned char data1[FOGWIDTH][4];
498 //unsigned char data2[FOGWIDTH][4];
501 r_refdef.fogmasktable_start = r_refdef.fog_start;
502 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
503 r_refdef.fogmasktable_range = r_refdef.fogrange;
504 r_refdef.fogmasktable_density = r_refdef.fog_density;
506 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
507 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
509 d = (x * r - r_refdef.fogmasktable_start);
510 if(developer_extra.integer)
511 Con_DPrintf("%f ", d);
513 if (r_fog_exp2.integer)
514 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
516 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
517 if(developer_extra.integer)
518 Con_DPrintf(" : %f ", alpha);
519 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
520 if(developer_extra.integer)
521 Con_DPrintf(" = %f\n", alpha);
522 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
525 for (x = 0;x < FOGWIDTH;x++)
527 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
532 //data2[x][0] = 255 - b;
533 //data2[x][1] = 255 - b;
534 //data2[x][2] = 255 - b;
537 if (r_texture_fogattenuation)
539 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
540 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
544 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
545 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
549 static void R_BuildFogHeightTexture(void)
551 unsigned char *inpixels;
559 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
560 if (r_refdef.fogheighttexturename[0])
561 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
564 r_refdef.fog_height_tablesize = 0;
565 if (r_texture_fogheighttexture)
566 R_FreeTexture(r_texture_fogheighttexture);
567 r_texture_fogheighttexture = NULL;
568 if (r_refdef.fog_height_table2d)
569 Mem_Free(r_refdef.fog_height_table2d);
570 r_refdef.fog_height_table2d = NULL;
571 if (r_refdef.fog_height_table1d)
572 Mem_Free(r_refdef.fog_height_table1d);
573 r_refdef.fog_height_table1d = NULL;
577 r_refdef.fog_height_tablesize = size;
578 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
579 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
580 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
582 // LordHavoc: now the magic - what is that table2d for? it is a cooked
583 // average fog color table accounting for every fog layer between a point
584 // and the camera. (Note: attenuation is handled separately!)
585 for (y = 0;y < size;y++)
587 for (x = 0;x < size;x++)
593 for (j = x;j <= y;j++)
595 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601 for (j = x;j >= y;j--)
603 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
608 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
609 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
610 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
611 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
614 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
617 //=======================================================================================================================================================
619 static const char *builtinshaderstring =
620 #include "shader_glsl.h"
623 const char *builtinhlslshaderstring =
624 #include "shader_hlsl.h"
627 char *glslshaderstring = NULL;
628 char *hlslshaderstring = NULL;
630 //=======================================================================================================================================================
632 typedef struct shaderpermutationinfo_s
637 shaderpermutationinfo_t;
639 typedef struct shadermodeinfo_s
641 const char *vertexfilename;
642 const char *geometryfilename;
643 const char *fragmentfilename;
649 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
650 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
652 {"#define USEDIFFUSE\n", " diffuse"},
653 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
654 {"#define USEVIEWTINT\n", " viewtint"},
655 {"#define USECOLORMAPPING\n", " colormapping"},
656 {"#define USESATURATION\n", " saturation"},
657 {"#define USEFOGINSIDE\n", " foginside"},
658 {"#define USEFOGOUTSIDE\n", " fogoutside"},
659 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
660 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
661 {"#define USEGAMMARAMPS\n", " gammaramps"},
662 {"#define USECUBEFILTER\n", " cubefilter"},
663 {"#define USEGLOW\n", " glow"},
664 {"#define USEBLOOM\n", " bloom"},
665 {"#define USESPECULAR\n", " specular"},
666 {"#define USEPOSTPROCESSING\n", " postprocessing"},
667 {"#define USEREFLECTION\n", " reflection"},
668 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
669 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
670 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
671 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
672 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
673 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
674 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
675 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
676 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
677 {"#define USEALPHAKILL\n", " alphakill"},
678 {"#define USEREFLECTCUBE\n", " reflectcube"},
679 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
680 {"#define USEBOUNCEGRID\n", " bouncegrid"},
681 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
682 {"#define USETRIPPY\n", " trippy"},
685 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
686 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
704 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
708 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
723 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
724 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
725 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
726 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
727 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
730 struct r_glsl_permutation_s;
731 typedef struct r_glsl_permutation_s
734 struct r_glsl_permutation_s *hashnext;
736 unsigned int permutation;
738 /// indicates if we have tried compiling this permutation already
740 /// 0 if compilation failed
742 // texture units assigned to each detected uniform
743 int tex_Texture_First;
744 int tex_Texture_Second;
745 int tex_Texture_GammaRamps;
746 int tex_Texture_Normal;
747 int tex_Texture_Color;
748 int tex_Texture_Gloss;
749 int tex_Texture_Glow;
750 int tex_Texture_SecondaryNormal;
751 int tex_Texture_SecondaryColor;
752 int tex_Texture_SecondaryGloss;
753 int tex_Texture_SecondaryGlow;
754 int tex_Texture_Pants;
755 int tex_Texture_Shirt;
756 int tex_Texture_FogHeightTexture;
757 int tex_Texture_FogMask;
758 int tex_Texture_Lightmap;
759 int tex_Texture_Deluxemap;
760 int tex_Texture_Attenuation;
761 int tex_Texture_Cube;
762 int tex_Texture_Refraction;
763 int tex_Texture_Reflection;
764 int tex_Texture_ShadowMap2D;
765 int tex_Texture_CubeProjection;
766 int tex_Texture_ScreenDepth;
767 int tex_Texture_ScreenNormalMap;
768 int tex_Texture_ScreenDiffuse;
769 int tex_Texture_ScreenSpecular;
770 int tex_Texture_ReflectMask;
771 int tex_Texture_ReflectCube;
772 int tex_Texture_BounceGrid;
773 /// locations of detected uniforms in program object, or -1 if not found
774 int loc_Texture_First;
775 int loc_Texture_Second;
776 int loc_Texture_GammaRamps;
777 int loc_Texture_Normal;
778 int loc_Texture_Color;
779 int loc_Texture_Gloss;
780 int loc_Texture_Glow;
781 int loc_Texture_SecondaryNormal;
782 int loc_Texture_SecondaryColor;
783 int loc_Texture_SecondaryGloss;
784 int loc_Texture_SecondaryGlow;
785 int loc_Texture_Pants;
786 int loc_Texture_Shirt;
787 int loc_Texture_FogHeightTexture;
788 int loc_Texture_FogMask;
789 int loc_Texture_Lightmap;
790 int loc_Texture_Deluxemap;
791 int loc_Texture_Attenuation;
792 int loc_Texture_Cube;
793 int loc_Texture_Refraction;
794 int loc_Texture_Reflection;
795 int loc_Texture_ShadowMap2D;
796 int loc_Texture_CubeProjection;
797 int loc_Texture_ScreenDepth;
798 int loc_Texture_ScreenNormalMap;
799 int loc_Texture_ScreenDiffuse;
800 int loc_Texture_ScreenSpecular;
801 int loc_Texture_ReflectMask;
802 int loc_Texture_ReflectCube;
803 int loc_Texture_BounceGrid;
805 int loc_BloomBlur_Parameters;
807 int loc_Color_Ambient;
808 int loc_Color_Diffuse;
809 int loc_Color_Specular;
813 int loc_DeferredColor_Ambient;
814 int loc_DeferredColor_Diffuse;
815 int loc_DeferredColor_Specular;
816 int loc_DeferredMod_Diffuse;
817 int loc_DeferredMod_Specular;
818 int loc_DistortScaleRefractReflect;
821 int loc_FogHeightFade;
823 int loc_FogPlaneViewDist;
824 int loc_FogRangeRecip;
827 int loc_LightPosition;
828 int loc_OffsetMapping_ScaleSteps;
829 int loc_OffsetMapping_LodDistance;
831 int loc_ReflectColor;
832 int loc_ReflectFactor;
833 int loc_ReflectOffset;
834 int loc_RefractColor;
836 int loc_ScreenCenterRefractReflect;
837 int loc_ScreenScaleRefractReflect;
838 int loc_ScreenToDepth;
839 int loc_ShadowMap_Parameters;
840 int loc_ShadowMap_TextureScale;
841 int loc_SpecularPower;
846 int loc_ViewTintColor;
848 int loc_ModelToLight;
850 int loc_BackgroundTexMatrix;
851 int loc_ModelViewProjectionMatrix;
852 int loc_ModelViewMatrix;
853 int loc_PixelToScreenTexCoord;
854 int loc_ModelToReflectCube;
855 int loc_ShadowMapMatrix;
856 int loc_BloomColorSubtract;
857 int loc_NormalmapScrollBlend;
858 int loc_BounceGridMatrix;
859 int loc_BounceGridIntensity;
861 r_glsl_permutation_t;
863 #define SHADERPERMUTATION_HASHSIZE 256
866 // non-degradable "lightweight" shader parameters to keep the permutations simpler
867 // these can NOT degrade! only use for simple stuff
870 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
871 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
872 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
873 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
874 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
875 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
876 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
877 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
879 #define SHADERSTATICPARMS_COUNT 8
881 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
882 static int shaderstaticparms_count = 0;
884 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
885 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
886 qboolean R_CompileShader_CheckStaticParms(void)
888 static int r_compileshader_staticparms_save[1];
889 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
890 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
893 if (r_glsl_saturation_redcompensate.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
895 if (r_glsl_vertextextureblend_usebothalphas.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
897 if (r_shadow_glossexact.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
899 if (r_glsl_postprocess.integer)
901 if (r_glsl_postprocess_uservec1_enable.integer)
902 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
903 if (r_glsl_postprocess_uservec2_enable.integer)
904 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
905 if (r_glsl_postprocess_uservec3_enable.integer)
906 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
907 if (r_glsl_postprocess_uservec4_enable.integer)
908 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
910 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
911 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
912 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
915 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
916 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
917 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
919 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
920 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
922 shaderstaticparms_count = 0;
925 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
926 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
927 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
928 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
929 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
930 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
931 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
932 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
935 /// information about each possible shader permutation
936 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
937 /// currently selected permutation
938 r_glsl_permutation_t *r_glsl_permutation;
939 /// storage for permutations linked in the hash table
940 memexpandablearray_t r_glsl_permutationarray;
942 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
944 //unsigned int hashdepth = 0;
945 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
946 r_glsl_permutation_t *p;
947 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
949 if (p->mode == mode && p->permutation == permutation)
951 //if (hashdepth > 10)
952 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
957 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
959 p->permutation = permutation;
960 p->hashnext = r_glsl_permutationhash[mode][hashindex];
961 r_glsl_permutationhash[mode][hashindex] = p;
962 //if (hashdepth > 10)
963 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
967 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
970 if (!filename || !filename[0])
972 if (!strcmp(filename, "glsl/default.glsl"))
974 if (!glslshaderstring)
976 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
977 if (glslshaderstring)
978 Con_DPrintf("Loading shaders from file %s...\n", filename);
980 glslshaderstring = (char *)builtinshaderstring;
982 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
983 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
986 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
989 if (printfromdisknotice)
990 Con_DPrintf("from disk %s... ", filename);
996 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1000 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1001 char *vertexstring, *geometrystring, *fragmentstring;
1002 char permutationname[256];
1003 int vertstrings_count = 0;
1004 int geomstrings_count = 0;
1005 int fragstrings_count = 0;
1006 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1007 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1008 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1015 permutationname[0] = 0;
1016 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1017 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1018 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1020 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1022 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1023 if(vid.support.gl20shaders130)
1025 vertstrings_list[vertstrings_count++] = "#version 130\n";
1026 geomstrings_list[geomstrings_count++] = "#version 130\n";
1027 fragstrings_list[fragstrings_count++] = "#version 130\n";
1028 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1029 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1030 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1033 // the first pretext is which type of shader to compile as
1034 // (later these will all be bound together as a program object)
1035 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1036 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1037 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1039 // the second pretext is the mode (for example a light source)
1040 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1041 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1042 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1043 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1045 // now add all the permutation pretexts
1046 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1048 if (permutation & (1<<i))
1050 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1051 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1052 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1053 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1057 // keep line numbers correct
1058 vertstrings_list[vertstrings_count++] = "\n";
1059 geomstrings_list[geomstrings_count++] = "\n";
1060 fragstrings_list[fragstrings_count++] = "\n";
1065 R_CompileShader_AddStaticParms(mode, permutation);
1066 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1067 vertstrings_count += shaderstaticparms_count;
1068 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1069 geomstrings_count += shaderstaticparms_count;
1070 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1071 fragstrings_count += shaderstaticparms_count;
1073 // now append the shader text itself
1074 vertstrings_list[vertstrings_count++] = vertexstring;
1075 geomstrings_list[geomstrings_count++] = geometrystring;
1076 fragstrings_list[fragstrings_count++] = fragmentstring;
1078 // if any sources were NULL, clear the respective list
1080 vertstrings_count = 0;
1081 if (!geometrystring)
1082 geomstrings_count = 0;
1083 if (!fragmentstring)
1084 fragstrings_count = 0;
1086 // compile the shader program
1087 if (vertstrings_count + geomstrings_count + fragstrings_count)
1088 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1092 qglUseProgram(p->program);CHECKGLERROR
1093 // look up all the uniform variable names we care about, so we don't
1094 // have to look them up every time we set them
1096 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1097 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1098 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1099 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1100 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1101 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1102 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1103 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1104 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1105 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1106 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1107 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1108 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1109 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1110 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1111 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1112 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1113 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1114 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1115 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1116 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1117 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1118 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1119 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1120 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1121 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1122 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1123 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1124 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1125 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1126 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1127 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1128 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1129 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1130 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1131 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1132 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1133 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1134 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1135 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1136 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1137 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1138 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1139 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1140 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1141 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1142 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1143 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1144 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1145 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1146 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1147 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1148 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1149 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1150 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1151 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1152 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1153 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1154 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1155 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1156 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1157 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1158 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1159 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1160 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1161 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1162 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1163 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1164 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1165 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1166 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1167 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1168 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1169 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1170 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1171 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1172 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1173 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1174 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1175 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1176 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1177 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1178 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1179 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1180 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1181 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1182 // initialize the samplers to refer to the texture units we use
1183 p->tex_Texture_First = -1;
1184 p->tex_Texture_Second = -1;
1185 p->tex_Texture_GammaRamps = -1;
1186 p->tex_Texture_Normal = -1;
1187 p->tex_Texture_Color = -1;
1188 p->tex_Texture_Gloss = -1;
1189 p->tex_Texture_Glow = -1;
1190 p->tex_Texture_SecondaryNormal = -1;
1191 p->tex_Texture_SecondaryColor = -1;
1192 p->tex_Texture_SecondaryGloss = -1;
1193 p->tex_Texture_SecondaryGlow = -1;
1194 p->tex_Texture_Pants = -1;
1195 p->tex_Texture_Shirt = -1;
1196 p->tex_Texture_FogHeightTexture = -1;
1197 p->tex_Texture_FogMask = -1;
1198 p->tex_Texture_Lightmap = -1;
1199 p->tex_Texture_Deluxemap = -1;
1200 p->tex_Texture_Attenuation = -1;
1201 p->tex_Texture_Cube = -1;
1202 p->tex_Texture_Refraction = -1;
1203 p->tex_Texture_Reflection = -1;
1204 p->tex_Texture_ShadowMap2D = -1;
1205 p->tex_Texture_CubeProjection = -1;
1206 p->tex_Texture_ScreenDepth = -1;
1207 p->tex_Texture_ScreenNormalMap = -1;
1208 p->tex_Texture_ScreenDiffuse = -1;
1209 p->tex_Texture_ScreenSpecular = -1;
1210 p->tex_Texture_ReflectMask = -1;
1211 p->tex_Texture_ReflectCube = -1;
1212 p->tex_Texture_BounceGrid = -1;
1214 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1215 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1216 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1217 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1218 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1219 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1220 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1221 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1222 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1223 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1224 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1225 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1226 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1227 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1228 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1229 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1230 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1231 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1232 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1233 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1234 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1235 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1236 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1237 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1238 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1239 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1240 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1241 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1242 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1243 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1245 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1248 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1252 Mem_Free(vertexstring);
1254 Mem_Free(geometrystring);
1256 Mem_Free(fragmentstring);
1259 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1261 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1262 if (r_glsl_permutation != perm)
1264 r_glsl_permutation = perm;
1265 if (!r_glsl_permutation->program)
1267 if (!r_glsl_permutation->compiled)
1268 R_GLSL_CompilePermutation(perm, mode, permutation);
1269 if (!r_glsl_permutation->program)
1271 // remove features until we find a valid permutation
1273 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1275 // reduce i more quickly whenever it would not remove any bits
1276 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1277 if (!(permutation & j))
1280 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1281 if (!r_glsl_permutation->compiled)
1282 R_GLSL_CompilePermutation(perm, mode, permutation);
1283 if (r_glsl_permutation->program)
1286 if (i >= SHADERPERMUTATION_COUNT)
1288 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1289 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1290 qglUseProgram(0);CHECKGLERROR
1291 return; // no bit left to clear, entire mode is broken
1296 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1298 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1299 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1300 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1307 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1308 extern D3DCAPS9 vid_d3d9caps;
1311 struct r_hlsl_permutation_s;
1312 typedef struct r_hlsl_permutation_s
1314 /// hash lookup data
1315 struct r_hlsl_permutation_s *hashnext;
1317 unsigned int permutation;
1319 /// indicates if we have tried compiling this permutation already
1321 /// NULL if compilation failed
1322 IDirect3DVertexShader9 *vertexshader;
1323 IDirect3DPixelShader9 *pixelshader;
1325 r_hlsl_permutation_t;
1327 typedef enum D3DVSREGISTER_e
1329 D3DVSREGISTER_TexMatrix = 0, // float4x4
1330 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1331 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1332 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1333 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1334 D3DVSREGISTER_ModelToLight = 20, // float4x4
1335 D3DVSREGISTER_EyePosition = 24,
1336 D3DVSREGISTER_FogPlane = 25,
1337 D3DVSREGISTER_LightDir = 26,
1338 D3DVSREGISTER_LightPosition = 27,
1342 typedef enum D3DPSREGISTER_e
1344 D3DPSREGISTER_Alpha = 0,
1345 D3DPSREGISTER_BloomBlur_Parameters = 1,
1346 D3DPSREGISTER_ClientTime = 2,
1347 D3DPSREGISTER_Color_Ambient = 3,
1348 D3DPSREGISTER_Color_Diffuse = 4,
1349 D3DPSREGISTER_Color_Specular = 5,
1350 D3DPSREGISTER_Color_Glow = 6,
1351 D3DPSREGISTER_Color_Pants = 7,
1352 D3DPSREGISTER_Color_Shirt = 8,
1353 D3DPSREGISTER_DeferredColor_Ambient = 9,
1354 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1355 D3DPSREGISTER_DeferredColor_Specular = 11,
1356 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1357 D3DPSREGISTER_DeferredMod_Specular = 13,
1358 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1359 D3DPSREGISTER_EyePosition = 15, // unused
1360 D3DPSREGISTER_FogColor = 16,
1361 D3DPSREGISTER_FogHeightFade = 17,
1362 D3DPSREGISTER_FogPlane = 18,
1363 D3DPSREGISTER_FogPlaneViewDist = 19,
1364 D3DPSREGISTER_FogRangeRecip = 20,
1365 D3DPSREGISTER_LightColor = 21,
1366 D3DPSREGISTER_LightDir = 22, // unused
1367 D3DPSREGISTER_LightPosition = 23,
1368 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1369 D3DPSREGISTER_PixelSize = 25,
1370 D3DPSREGISTER_ReflectColor = 26,
1371 D3DPSREGISTER_ReflectFactor = 27,
1372 D3DPSREGISTER_ReflectOffset = 28,
1373 D3DPSREGISTER_RefractColor = 29,
1374 D3DPSREGISTER_Saturation = 30,
1375 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1376 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1377 D3DPSREGISTER_ScreenToDepth = 33,
1378 D3DPSREGISTER_ShadowMap_Parameters = 34,
1379 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1380 D3DPSREGISTER_SpecularPower = 36,
1381 D3DPSREGISTER_UserVec1 = 37,
1382 D3DPSREGISTER_UserVec2 = 38,
1383 D3DPSREGISTER_UserVec3 = 39,
1384 D3DPSREGISTER_UserVec4 = 40,
1385 D3DPSREGISTER_ViewTintColor = 41,
1386 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1387 D3DPSREGISTER_BloomColorSubtract = 43,
1388 D3DPSREGISTER_ViewToLight = 44, // float4x4
1389 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1390 D3DPSREGISTER_NormalmapScrollBlend = 52,
1391 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1396 /// information about each possible shader permutation
1397 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1398 /// currently selected permutation
1399 r_hlsl_permutation_t *r_hlsl_permutation;
1400 /// storage for permutations linked in the hash table
1401 memexpandablearray_t r_hlsl_permutationarray;
1403 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1405 //unsigned int hashdepth = 0;
1406 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1407 r_hlsl_permutation_t *p;
1408 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1410 if (p->mode == mode && p->permutation == permutation)
1412 //if (hashdepth > 10)
1413 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1418 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1420 p->permutation = permutation;
1421 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1422 r_hlsl_permutationhash[mode][hashindex] = p;
1423 //if (hashdepth > 10)
1424 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1428 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1431 if (!filename || !filename[0])
1433 if (!strcmp(filename, "hlsl/default.hlsl"))
1435 if (!hlslshaderstring)
1437 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1438 if (hlslshaderstring)
1439 Con_DPrintf("Loading shaders from file %s...\n", filename);
1441 hlslshaderstring = (char *)builtinhlslshaderstring;
1443 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1444 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1445 return shaderstring;
1447 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1450 if (printfromdisknotice)
1451 Con_DPrintf("from disk %s... ", filename);
1452 return shaderstring;
1454 return shaderstring;
1458 //#include <d3dx9shader.h>
1459 //#include <d3dx9mesh.h>
1461 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1463 DWORD *vsbin = NULL;
1464 DWORD *psbin = NULL;
1465 fs_offset_t vsbinsize;
1466 fs_offset_t psbinsize;
1467 // IDirect3DVertexShader9 *vs = NULL;
1468 // IDirect3DPixelShader9 *ps = NULL;
1469 ID3DXBuffer *vslog = NULL;
1470 ID3DXBuffer *vsbuffer = NULL;
1471 ID3DXConstantTable *vsconstanttable = NULL;
1472 ID3DXBuffer *pslog = NULL;
1473 ID3DXBuffer *psbuffer = NULL;
1474 ID3DXConstantTable *psconstanttable = NULL;
1477 char temp[MAX_INPUTLINE];
1478 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1479 qboolean debugshader = gl_paranoid.integer != 0;
1480 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1481 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1484 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1485 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1487 if ((!vsbin && vertstring) || (!psbin && fragstring))
1489 const char* dllnames_d3dx9 [] =
1513 dllhandle_t d3dx9_dll = NULL;
1514 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1515 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1516 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1517 dllfunction_t d3dx9_dllfuncs[] =
1519 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1520 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1521 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1524 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1526 DWORD shaderflags = 0;
1528 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1529 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1530 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1531 if (vertstring && vertstring[0])
1535 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1536 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1537 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1538 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1541 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1544 vsbinsize = vsbuffer->GetBufferSize();
1545 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1546 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1547 vsbuffer->Release();
1551 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1552 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1556 if (fragstring && fragstring[0])
1560 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1561 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1562 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1563 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1566 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1569 psbinsize = psbuffer->GetBufferSize();
1570 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1571 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1572 psbuffer->Release();
1576 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1577 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1581 Sys_UnloadLibrary(&d3dx9_dll);
1584 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1588 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1589 if (FAILED(vsresult))
1590 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1591 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1592 if (FAILED(psresult))
1593 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1595 // free the shader data
1596 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1597 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1600 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1603 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1604 int vertstring_length = 0;
1605 int geomstring_length = 0;
1606 int fragstring_length = 0;
1608 char *vertexstring, *geometrystring, *fragmentstring;
1609 char *vertstring, *geomstring, *fragstring;
1610 char permutationname[256];
1611 char cachename[256];
1612 int vertstrings_count = 0;
1613 int geomstrings_count = 0;
1614 int fragstrings_count = 0;
1615 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1616 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1617 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1622 p->vertexshader = NULL;
1623 p->pixelshader = NULL;
1625 permutationname[0] = 0;
1627 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1628 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1629 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1631 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1632 strlcat(cachename, "hlsl/", sizeof(cachename));
1634 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1635 vertstrings_count = 0;
1636 geomstrings_count = 0;
1637 fragstrings_count = 0;
1638 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1639 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1640 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1642 // the first pretext is which type of shader to compile as
1643 // (later these will all be bound together as a program object)
1644 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1645 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1646 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1648 // the second pretext is the mode (for example a light source)
1649 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1650 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1651 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1652 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1653 strlcat(cachename, modeinfo->name, sizeof(cachename));
1655 // now add all the permutation pretexts
1656 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1658 if (permutation & (1<<i))
1660 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1661 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1662 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1663 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1664 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1668 // keep line numbers correct
1669 vertstrings_list[vertstrings_count++] = "\n";
1670 geomstrings_list[geomstrings_count++] = "\n";
1671 fragstrings_list[fragstrings_count++] = "\n";
1676 R_CompileShader_AddStaticParms(mode, permutation);
1677 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1678 vertstrings_count += shaderstaticparms_count;
1679 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1680 geomstrings_count += shaderstaticparms_count;
1681 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1682 fragstrings_count += shaderstaticparms_count;
1684 // replace spaces in the cachename with _ characters
1685 for (i = 0;cachename[i];i++)
1686 if (cachename[i] == ' ')
1689 // now append the shader text itself
1690 vertstrings_list[vertstrings_count++] = vertexstring;
1691 geomstrings_list[geomstrings_count++] = geometrystring;
1692 fragstrings_list[fragstrings_count++] = fragmentstring;
1694 // if any sources were NULL, clear the respective list
1696 vertstrings_count = 0;
1697 if (!geometrystring)
1698 geomstrings_count = 0;
1699 if (!fragmentstring)
1700 fragstrings_count = 0;
1702 vertstring_length = 0;
1703 for (i = 0;i < vertstrings_count;i++)
1704 vertstring_length += strlen(vertstrings_list[i]);
1705 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1706 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1707 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1709 geomstring_length = 0;
1710 for (i = 0;i < geomstrings_count;i++)
1711 geomstring_length += strlen(geomstrings_list[i]);
1712 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1713 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1714 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1716 fragstring_length = 0;
1717 for (i = 0;i < fragstrings_count;i++)
1718 fragstring_length += strlen(fragstrings_list[i]);
1719 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1720 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1721 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1723 // try to load the cached shader, or generate one
1724 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1726 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1727 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1729 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1733 Mem_Free(vertstring);
1735 Mem_Free(geomstring);
1737 Mem_Free(fragstring);
1739 Mem_Free(vertexstring);
1741 Mem_Free(geometrystring);
1743 Mem_Free(fragmentstring);
1746 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1747 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1748 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);}
1749 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);}
1750 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);}
1751 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);}
1753 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1754 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1755 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);}
1756 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);}
1757 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);}
1758 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);}
1760 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1762 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1763 if (r_hlsl_permutation != perm)
1765 r_hlsl_permutation = perm;
1766 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1768 if (!r_hlsl_permutation->compiled)
1769 R_HLSL_CompilePermutation(perm, mode, permutation);
1770 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1772 // remove features until we find a valid permutation
1774 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1776 // reduce i more quickly whenever it would not remove any bits
1777 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1778 if (!(permutation & j))
1781 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1782 if (!r_hlsl_permutation->compiled)
1783 R_HLSL_CompilePermutation(perm, mode, permutation);
1784 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1787 if (i >= SHADERPERMUTATION_COUNT)
1789 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1790 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1791 return; // no bit left to clear, entire mode is broken
1795 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1796 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1798 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1799 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1800 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1804 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1806 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1807 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1808 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1809 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1812 void R_GLSL_Restart_f(void)
1814 unsigned int i, limit;
1815 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1816 Mem_Free(glslshaderstring);
1817 glslshaderstring = NULL;
1818 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1819 Mem_Free(hlslshaderstring);
1820 hlslshaderstring = NULL;
1821 switch(vid.renderpath)
1823 case RENDERPATH_D3D9:
1826 r_hlsl_permutation_t *p;
1827 r_hlsl_permutation = NULL;
1828 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1829 for (i = 0;i < limit;i++)
1831 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1833 if (p->vertexshader)
1834 IDirect3DVertexShader9_Release(p->vertexshader);
1836 IDirect3DPixelShader9_Release(p->pixelshader);
1837 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1840 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1844 case RENDERPATH_D3D10:
1845 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1847 case RENDERPATH_D3D11:
1848 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1850 case RENDERPATH_GL20:
1851 case RENDERPATH_GLES2:
1853 r_glsl_permutation_t *p;
1854 r_glsl_permutation = NULL;
1855 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1856 for (i = 0;i < limit;i++)
1858 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1860 GL_Backend_FreeProgram(p->program);
1861 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1864 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1867 case RENDERPATH_GL11:
1868 case RENDERPATH_GL13:
1869 case RENDERPATH_GLES1:
1871 case RENDERPATH_SOFT:
1876 void R_GLSL_DumpShader_f(void)
1881 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1884 FS_Print(file, "/* The engine may define the following macros:\n");
1885 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1886 for (i = 0;i < SHADERMODE_COUNT;i++)
1887 FS_Print(file, glslshadermodeinfo[i].pretext);
1888 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1889 FS_Print(file, shaderpermutationinfo[i].pretext);
1890 FS_Print(file, "*/\n");
1891 FS_Print(file, builtinshaderstring);
1893 Con_Printf("glsl/default.glsl written\n");
1896 Con_Printf("failed to write to glsl/default.glsl\n");
1898 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1901 FS_Print(file, "/* The engine may define the following macros:\n");
1902 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1903 for (i = 0;i < SHADERMODE_COUNT;i++)
1904 FS_Print(file, hlslshadermodeinfo[i].pretext);
1905 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1906 FS_Print(file, shaderpermutationinfo[i].pretext);
1907 FS_Print(file, "*/\n");
1908 FS_Print(file, builtinhlslshaderstring);
1910 Con_Printf("hlsl/default.hlsl written\n");
1913 Con_Printf("failed to write to hlsl/default.hlsl\n");
1916 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1918 unsigned int permutation = 0;
1919 if (r_trippy.integer && !notrippy)
1920 permutation |= SHADERPERMUTATION_TRIPPY;
1921 permutation |= SHADERPERMUTATION_VIEWTINT;
1923 permutation |= SHADERPERMUTATION_DIFFUSE;
1925 permutation |= SHADERPERMUTATION_SPECULAR;
1926 if (texturemode == GL_MODULATE)
1927 permutation |= SHADERPERMUTATION_COLORMAPPING;
1928 else if (texturemode == GL_ADD)
1929 permutation |= SHADERPERMUTATION_GLOW;
1930 else if (texturemode == GL_DECAL)
1931 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1932 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1933 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1935 texturemode = GL_MODULATE;
1936 if (vid.allowalphatocoverage)
1937 GL_AlphaToCoverage(false);
1938 switch (vid.renderpath)
1940 case RENDERPATH_D3D9:
1942 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1943 R_Mesh_TexBind(GL20TU_FIRST , first );
1944 R_Mesh_TexBind(GL20TU_SECOND, second);
1945 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1946 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1949 case RENDERPATH_D3D10:
1950 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952 case RENDERPATH_D3D11:
1953 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955 case RENDERPATH_GL20:
1956 case RENDERPATH_GLES2:
1957 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1958 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1959 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1960 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1961 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1963 case RENDERPATH_GL13:
1964 case RENDERPATH_GLES1:
1965 R_Mesh_TexBind(0, first );
1966 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1967 R_Mesh_TexBind(1, second);
1969 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1971 case RENDERPATH_GL11:
1972 R_Mesh_TexBind(0, first );
1974 case RENDERPATH_SOFT:
1975 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1976 R_Mesh_TexBind(GL20TU_FIRST , first );
1977 R_Mesh_TexBind(GL20TU_SECOND, second);
1982 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1984 unsigned int permutation = 0;
1985 if (r_trippy.integer && !notrippy)
1986 permutation |= SHADERPERMUTATION_TRIPPY;
1987 if (vid.allowalphatocoverage)
1988 GL_AlphaToCoverage(false);
1989 switch (vid.renderpath)
1991 case RENDERPATH_D3D9:
1993 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1996 case RENDERPATH_D3D10:
1997 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1999 case RENDERPATH_D3D11:
2000 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2002 case RENDERPATH_GL20:
2003 case RENDERPATH_GLES2:
2004 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006 case RENDERPATH_GL13:
2007 case RENDERPATH_GLES1:
2008 R_Mesh_TexBind(0, 0);
2009 R_Mesh_TexBind(1, 0);
2011 case RENDERPATH_GL11:
2012 R_Mesh_TexBind(0, 0);
2014 case RENDERPATH_SOFT:
2015 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2020 void R_SetupShader_ShowDepth(qboolean notrippy)
2022 int permutation = 0;
2023 if (r_trippy.integer && !notrippy)
2024 permutation |= SHADERPERMUTATION_TRIPPY;
2025 if (vid.allowalphatocoverage)
2026 GL_AlphaToCoverage(false);
2027 switch (vid.renderpath)
2029 case RENDERPATH_D3D9:
2031 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2034 case RENDERPATH_D3D10:
2035 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2037 case RENDERPATH_D3D11:
2038 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2040 case RENDERPATH_GL20:
2041 case RENDERPATH_GLES2:
2042 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2044 case RENDERPATH_GL13:
2045 case RENDERPATH_GLES1:
2047 case RENDERPATH_GL11:
2049 case RENDERPATH_SOFT:
2050 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2055 extern qboolean r_shadow_usingdeferredprepass;
2056 extern cvar_t r_shadow_deferred_8bitrange;
2057 extern rtexture_t *r_shadow_attenuationgradienttexture;
2058 extern rtexture_t *r_shadow_attenuation2dtexture;
2059 extern rtexture_t *r_shadow_attenuation3dtexture;
2060 extern qboolean r_shadow_usingshadowmap2d;
2061 extern qboolean r_shadow_usingshadowmaportho;
2062 extern float r_shadow_shadowmap_texturescale[2];
2063 extern float r_shadow_shadowmap_parameters[4];
2064 extern qboolean r_shadow_shadowmapvsdct;
2065 extern qboolean r_shadow_shadowmapsampler;
2066 extern int r_shadow_shadowmappcf;
2067 extern rtexture_t *r_shadow_shadowmap2dtexture;
2068 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2069 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2070 extern matrix4x4_t r_shadow_shadowmapmatrix;
2071 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2072 extern int r_shadow_prepass_width;
2073 extern int r_shadow_prepass_height;
2074 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2075 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2076 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2077 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2078 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2080 #define BLENDFUNC_ALLOWS_COLORMOD 1
2081 #define BLENDFUNC_ALLOWS_FOG 2
2082 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2083 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2084 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2085 static int R_BlendFuncFlags(int src, int dst)
2089 // a blendfunc allows colormod if:
2090 // a) it can never keep the destination pixel invariant, or
2091 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2092 // this is to prevent unintended side effects from colormod
2094 // a blendfunc allows fog if:
2095 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2096 // this is to prevent unintended side effects from fog
2098 // these checks are the output of fogeval.pl
2100 r |= BLENDFUNC_ALLOWS_COLORMOD;
2101 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2102 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2103 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2105 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2106 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2109 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2110 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2111 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2112 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2113 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2114 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2115 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2116 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2117 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2118 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2119 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2120 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2121 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2126 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)
2128 // select a permutation of the lighting shader appropriate to this
2129 // combination of texture, entity, light source, and fogging, only use the
2130 // minimum features necessary to avoid wasting rendering time in the
2131 // fragment shader on features that are not being used
2132 unsigned int permutation = 0;
2133 unsigned int mode = 0;
2135 static float dummy_colormod[3] = {1, 1, 1};
2136 float *colormod = rsurface.colormod;
2138 matrix4x4_t tempmatrix;
2139 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2140 if (r_trippy.integer && !notrippy)
2141 permutation |= SHADERPERMUTATION_TRIPPY;
2142 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2143 permutation |= SHADERPERMUTATION_ALPHAKILL;
2144 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2145 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2146 if (rsurfacepass == RSURFPASS_BACKGROUND)
2148 // distorted background
2149 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2151 mode = SHADERMODE_WATER;
2152 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2154 // this is the right thing to do for wateralpha
2155 GL_BlendFunc(GL_ONE, GL_ZERO);
2156 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2160 // this is the right thing to do for entity alpha
2161 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2162 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2165 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2167 mode = SHADERMODE_REFRACTION;
2168 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2169 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2173 mode = SHADERMODE_GENERIC;
2174 permutation |= SHADERPERMUTATION_DIFFUSE;
2175 GL_BlendFunc(GL_ONE, GL_ZERO);
2176 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2178 if (vid.allowalphatocoverage)
2179 GL_AlphaToCoverage(false);
2181 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2183 if (r_glsl_offsetmapping.integer)
2185 switch(rsurface.texture->offsetmapping)
2187 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2188 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2189 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2190 case OFFSETMAPPING_OFF: break;
2193 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2194 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2195 // normalmap (deferred prepass), may use alpha test on diffuse
2196 mode = SHADERMODE_DEFERREDGEOMETRY;
2197 GL_BlendFunc(GL_ONE, GL_ZERO);
2198 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2199 if (vid.allowalphatocoverage)
2200 GL_AlphaToCoverage(false);
2202 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2204 if (r_glsl_offsetmapping.integer)
2206 switch(rsurface.texture->offsetmapping)
2208 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2209 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2210 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2211 case OFFSETMAPPING_OFF: break;
2214 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2215 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2217 mode = SHADERMODE_LIGHTSOURCE;
2218 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2219 permutation |= SHADERPERMUTATION_CUBEFILTER;
2220 if (diffusescale > 0)
2221 permutation |= SHADERPERMUTATION_DIFFUSE;
2222 if (specularscale > 0)
2223 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2224 if (r_refdef.fogenabled)
2225 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2226 if (rsurface.texture->colormapping)
2227 permutation |= SHADERPERMUTATION_COLORMAPPING;
2228 if (r_shadow_usingshadowmap2d)
2230 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2231 if(r_shadow_shadowmapvsdct)
2232 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2234 if (r_shadow_shadowmapsampler)
2235 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2236 if (r_shadow_shadowmappcf > 1)
2237 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2238 else if (r_shadow_shadowmappcf)
2239 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2241 if (rsurface.texture->reflectmasktexture)
2242 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2243 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2244 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2245 if (vid.allowalphatocoverage)
2246 GL_AlphaToCoverage(false);
2248 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2250 if (r_glsl_offsetmapping.integer)
2252 switch(rsurface.texture->offsetmapping)
2254 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2255 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2256 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257 case OFFSETMAPPING_OFF: break;
2260 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2261 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2262 // unshaded geometry (fullbright or ambient model lighting)
2263 mode = SHADERMODE_FLATCOLOR;
2264 ambientscale = diffusescale = specularscale = 0;
2265 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2266 permutation |= SHADERPERMUTATION_GLOW;
2267 if (r_refdef.fogenabled)
2268 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2269 if (rsurface.texture->colormapping)
2270 permutation |= SHADERPERMUTATION_COLORMAPPING;
2271 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2273 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2274 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2276 if (r_shadow_shadowmapsampler)
2277 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2278 if (r_shadow_shadowmappcf > 1)
2279 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2280 else if (r_shadow_shadowmappcf)
2281 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2283 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2284 permutation |= SHADERPERMUTATION_REFLECTION;
2285 if (rsurface.texture->reflectmasktexture)
2286 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2287 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2288 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2289 // when using alphatocoverage, we don't need alphakill
2290 if (vid.allowalphatocoverage)
2292 if (r_transparent_alphatocoverage.integer)
2294 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2295 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2298 GL_AlphaToCoverage(false);
2301 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2303 if (r_glsl_offsetmapping.integer)
2305 switch(rsurface.texture->offsetmapping)
2307 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2308 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2309 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2310 case OFFSETMAPPING_OFF: break;
2313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2314 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2315 // directional model lighting
2316 mode = SHADERMODE_LIGHTDIRECTION;
2317 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2318 permutation |= SHADERPERMUTATION_GLOW;
2319 permutation |= SHADERPERMUTATION_DIFFUSE;
2320 if (specularscale > 0)
2321 permutation |= SHADERPERMUTATION_SPECULAR;
2322 if (r_refdef.fogenabled)
2323 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2324 if (rsurface.texture->colormapping)
2325 permutation |= SHADERPERMUTATION_COLORMAPPING;
2326 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2328 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2329 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2331 if (r_shadow_shadowmapsampler)
2332 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2333 if (r_shadow_shadowmappcf > 1)
2334 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2335 else if (r_shadow_shadowmappcf)
2336 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2338 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2339 permutation |= SHADERPERMUTATION_REFLECTION;
2340 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2341 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2342 if (rsurface.texture->reflectmasktexture)
2343 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2344 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2346 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2347 if (r_shadow_bouncegriddirectional)
2348 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2350 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2351 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352 // when using alphatocoverage, we don't need alphakill
2353 if (vid.allowalphatocoverage)
2355 if (r_transparent_alphatocoverage.integer)
2357 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2358 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2361 GL_AlphaToCoverage(false);
2364 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2366 if (r_glsl_offsetmapping.integer)
2368 switch(rsurface.texture->offsetmapping)
2370 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2371 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2372 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2373 case OFFSETMAPPING_OFF: break;
2376 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2377 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2378 // ambient model lighting
2379 mode = SHADERMODE_LIGHTDIRECTION;
2380 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2381 permutation |= SHADERPERMUTATION_GLOW;
2382 if (r_refdef.fogenabled)
2383 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2384 if (rsurface.texture->colormapping)
2385 permutation |= SHADERPERMUTATION_COLORMAPPING;
2386 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2388 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2389 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2391 if (r_shadow_shadowmapsampler)
2392 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2393 if (r_shadow_shadowmappcf > 1)
2394 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2395 else if (r_shadow_shadowmappcf)
2396 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2398 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2399 permutation |= SHADERPERMUTATION_REFLECTION;
2400 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2401 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2402 if (rsurface.texture->reflectmasktexture)
2403 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2404 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2406 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2407 if (r_shadow_bouncegriddirectional)
2408 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2410 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2411 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2412 // when using alphatocoverage, we don't need alphakill
2413 if (vid.allowalphatocoverage)
2415 if (r_transparent_alphatocoverage.integer)
2417 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2418 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2421 GL_AlphaToCoverage(false);
2426 if (r_glsl_offsetmapping.integer)
2428 switch(rsurface.texture->offsetmapping)
2430 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2431 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2432 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2433 case OFFSETMAPPING_OFF: break;
2436 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2437 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2439 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2440 permutation |= SHADERPERMUTATION_GLOW;
2441 if (r_refdef.fogenabled)
2442 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2443 if (rsurface.texture->colormapping)
2444 permutation |= SHADERPERMUTATION_COLORMAPPING;
2445 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2447 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2448 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2450 if (r_shadow_shadowmapsampler)
2451 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2452 if (r_shadow_shadowmappcf > 1)
2453 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2454 else if (r_shadow_shadowmappcf)
2455 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2457 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2458 permutation |= SHADERPERMUTATION_REFLECTION;
2459 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2460 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2461 if (rsurface.texture->reflectmasktexture)
2462 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2463 if (FAKELIGHT_ENABLED)
2465 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2466 mode = SHADERMODE_FAKELIGHT;
2467 permutation |= SHADERPERMUTATION_DIFFUSE;
2468 if (specularscale > 0)
2469 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2471 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2473 // deluxemapping (light direction texture)
2474 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2475 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2477 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2478 permutation |= SHADERPERMUTATION_DIFFUSE;
2479 if (specularscale > 0)
2480 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2482 else if (r_glsl_deluxemapping.integer >= 2)
2484 // fake deluxemapping (uniform light direction in tangentspace)
2485 if (rsurface.uselightmaptexture)
2486 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2488 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2489 permutation |= SHADERPERMUTATION_DIFFUSE;
2490 if (specularscale > 0)
2491 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2493 else if (rsurface.uselightmaptexture)
2495 // ordinary lightmapping (q1bsp, q3bsp)
2496 mode = SHADERMODE_LIGHTMAP;
2500 // ordinary vertex coloring (q3bsp)
2501 mode = SHADERMODE_VERTEXCOLOR;
2503 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2505 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2506 if (r_shadow_bouncegriddirectional)
2507 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2509 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2510 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2511 // when using alphatocoverage, we don't need alphakill
2512 if (vid.allowalphatocoverage)
2514 if (r_transparent_alphatocoverage.integer)
2516 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2517 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2520 GL_AlphaToCoverage(false);
2523 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2524 colormod = dummy_colormod;
2525 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2526 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2527 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2528 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2529 switch(vid.renderpath)
2531 case RENDERPATH_D3D9:
2533 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), texturenumsurfaces, texturesurfacelist);
2534 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2535 R_SetupShader_SetPermutationHLSL(mode, permutation);
2536 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2537 if (mode == SHADERMODE_LIGHTSOURCE)
2539 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2540 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2544 if (mode == SHADERMODE_LIGHTDIRECTION)
2546 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2549 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2550 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2551 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2552 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2553 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2555 if (mode == SHADERMODE_LIGHTSOURCE)
2557 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2558 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2559 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2560 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2561 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2563 // additive passes are only darkened by fog, not tinted
2564 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2565 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2569 if (mode == SHADERMODE_FLATCOLOR)
2571 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2573 else if (mode == SHADERMODE_LIGHTDIRECTION)
2575 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]);
2576 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2577 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);
2578 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2579 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2580 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2581 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2585 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2586 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2587 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);
2588 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2589 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2591 // additive passes are only darkened by fog, not tinted
2592 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2593 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2595 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2596 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);
2597 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2598 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2599 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2600 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2601 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2602 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2603 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2604 if (mode == SHADERMODE_WATER)
2605 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2607 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2608 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2609 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2610 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2611 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2612 if (rsurface.texture->pantstexture)
2613 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2615 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2616 if (rsurface.texture->shirttexture)
2617 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2619 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2620 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2621 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2622 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2623 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2624 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2625 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2626 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2627 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2628 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2630 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer)
2631 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2632 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2634 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2635 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2636 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2637 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2638 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2639 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2640 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2641 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2642 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2643 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2644 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2645 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2646 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2647 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2648 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2649 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2650 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2651 if (rsurfacepass == RSURFPASS_BACKGROUND)
2653 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2654 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2655 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2659 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2661 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2662 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2663 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2664 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2665 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2667 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2668 if (rsurface.rtlight)
2670 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2671 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2676 case RENDERPATH_D3D10:
2677 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2679 case RENDERPATH_D3D11:
2680 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2682 case RENDERPATH_GL20:
2683 case RENDERPATH_GLES2:
2684 if (!vid.useinterleavedarrays)
2686 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), texturenumsurfaces, texturesurfacelist);
2687 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2688 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2689 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2690 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2691 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2692 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2693 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2697 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), texturenumsurfaces, texturesurfacelist);
2698 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2700 R_SetupShader_SetPermutationGLSL(mode, permutation);
2701 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2702 if (mode == SHADERMODE_LIGHTSOURCE)
2704 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2705 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2706 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2707 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2708 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2709 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);
2711 // additive passes are only darkened by fog, not tinted
2712 if (r_glsl_permutation->loc_FogColor >= 0)
2713 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2714 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);
2718 if (mode == SHADERMODE_FLATCOLOR)
2720 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2722 else if (mode == SHADERMODE_LIGHTDIRECTION)
2724 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]);
2725 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]);
2726 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);
2727 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2728 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2729 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]);
2730 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]);
2734 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]);
2735 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]);
2736 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);
2737 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2738 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2740 // additive passes are only darkened by fog, not tinted
2741 if (r_glsl_permutation->loc_FogColor >= 0)
2743 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2744 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2746 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2748 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);
2749 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2750 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2751 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]);
2752 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]);
2753 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2754 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2755 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);
2756 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]);
2758 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2759 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2760 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2761 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2762 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2764 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2765 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2766 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2767 if (r_glsl_permutation->loc_Color_Pants >= 0)
2769 if (rsurface.texture->pantstexture)
2770 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2772 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2774 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2776 if (rsurface.texture->shirttexture)
2777 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2779 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2781 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]);
2782 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2783 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2784 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2785 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2786 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2787 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2788 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2789 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2791 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2792 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]);
2793 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2794 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2795 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2797 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2798 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2799 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2800 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2801 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2802 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2803 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2804 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2805 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2806 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2807 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2808 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2809 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2810 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2811 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);
2812 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2813 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2814 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2815 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2816 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2817 if (rsurfacepass == RSURFPASS_BACKGROUND)
2819 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);
2820 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);
2821 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);
2825 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);
2827 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2828 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2829 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2830 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2831 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2833 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2834 if (rsurface.rtlight)
2836 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2837 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2840 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2843 case RENDERPATH_GL11:
2844 case RENDERPATH_GL13:
2845 case RENDERPATH_GLES1:
2847 case RENDERPATH_SOFT:
2848 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), texturenumsurfaces, texturesurfacelist);
2849 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2850 R_SetupShader_SetPermutationSoft(mode, permutation);
2851 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2852 if (mode == SHADERMODE_LIGHTSOURCE)
2854 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2855 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2856 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2857 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2858 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2859 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2861 // additive passes are only darkened by fog, not tinted
2862 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2863 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2867 if (mode == SHADERMODE_FLATCOLOR)
2869 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2871 else if (mode == SHADERMODE_LIGHTDIRECTION)
2873 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]);
2874 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2875 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);
2876 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2877 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2878 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]);
2879 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2883 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2885 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);
2886 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2887 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2889 // additive passes are only darkened by fog, not tinted
2890 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2891 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2893 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2894 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);
2895 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2896 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2897 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]);
2898 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]);
2899 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2900 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2901 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2902 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2904 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2905 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2906 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2907 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2908 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2910 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2911 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2912 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2913 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2915 if (rsurface.texture->pantstexture)
2916 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2918 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2920 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2922 if (rsurface.texture->shirttexture)
2923 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2925 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2927 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2928 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2929 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2930 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2931 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2932 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2933 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2934 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2935 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2937 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2938 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2940 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2941 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2942 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2943 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2944 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2945 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2946 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2947 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2948 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2949 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2950 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2951 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2952 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2953 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2954 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2955 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2956 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2957 if (rsurfacepass == RSURFPASS_BACKGROUND)
2959 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2960 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2961 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2965 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2967 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2968 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2969 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2970 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2971 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2973 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2974 if (rsurface.rtlight)
2976 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2977 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2984 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2986 // select a permutation of the lighting shader appropriate to this
2987 // combination of texture, entity, light source, and fogging, only use the
2988 // minimum features necessary to avoid wasting rendering time in the
2989 // fragment shader on features that are not being used
2990 unsigned int permutation = 0;
2991 unsigned int mode = 0;
2992 const float *lightcolorbase = rtlight->currentcolor;
2993 float ambientscale = rtlight->ambientscale;
2994 float diffusescale = rtlight->diffusescale;
2995 float specularscale = rtlight->specularscale;
2996 // this is the location of the light in view space
2997 vec3_t viewlightorigin;
2998 // this transforms from view space (camera) to light space (cubemap)
2999 matrix4x4_t viewtolight;
3000 matrix4x4_t lighttoview;
3001 float viewtolight16f[16];
3002 float range = 1.0f / r_shadow_deferred_8bitrange.value;
3004 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3005 if (rtlight->currentcubemap != r_texture_whitecube)
3006 permutation |= SHADERPERMUTATION_CUBEFILTER;
3007 if (diffusescale > 0)
3008 permutation |= SHADERPERMUTATION_DIFFUSE;
3009 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3010 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3011 if (r_shadow_usingshadowmap2d)
3013 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3014 if (r_shadow_shadowmapvsdct)
3015 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3017 if (r_shadow_shadowmapsampler)
3018 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3019 if (r_shadow_shadowmappcf > 1)
3020 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3021 else if (r_shadow_shadowmappcf)
3022 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3024 if (vid.allowalphatocoverage)
3025 GL_AlphaToCoverage(false);
3026 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3027 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3028 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3029 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3030 switch(vid.renderpath)
3032 case RENDERPATH_D3D9:
3034 R_SetupShader_SetPermutationHLSL(mode, permutation);
3035 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3036 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3037 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3038 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3039 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3040 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3041 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3042 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);
3043 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3044 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3046 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3047 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3048 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3049 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3050 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3051 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3054 case RENDERPATH_D3D10:
3055 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3057 case RENDERPATH_D3D11:
3058 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3060 case RENDERPATH_GL20:
3061 case RENDERPATH_GLES2:
3062 R_SetupShader_SetPermutationGLSL(mode, permutation);
3063 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3064 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3065 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3066 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3067 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3068 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3069 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3070 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);
3071 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]);
3072 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3074 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3075 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3076 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3077 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3078 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3079 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3081 case RENDERPATH_GL11:
3082 case RENDERPATH_GL13:
3083 case RENDERPATH_GLES1:
3085 case RENDERPATH_SOFT:
3086 R_SetupShader_SetPermutationGLSL(mode, permutation);
3087 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3088 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3089 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3090 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3091 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3092 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3093 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3094 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);
3095 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3096 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3098 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3099 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3100 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3101 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3102 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3103 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3108 #define SKINFRAME_HASH 1024
3112 int loadsequence; // incremented each level change
3113 memexpandablearray_t array;
3114 skinframe_t *hash[SKINFRAME_HASH];
3117 r_skinframe_t r_skinframe;
3119 void R_SkinFrame_PrepareForPurge(void)
3121 r_skinframe.loadsequence++;
3122 // wrap it without hitting zero
3123 if (r_skinframe.loadsequence >= 200)
3124 r_skinframe.loadsequence = 1;
3127 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3131 // mark the skinframe as used for the purging code
3132 skinframe->loadsequence = r_skinframe.loadsequence;
3135 void R_SkinFrame_Purge(void)
3139 for (i = 0;i < SKINFRAME_HASH;i++)
3141 for (s = r_skinframe.hash[i];s;s = s->next)
3143 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3145 if (s->merged == s->base)
3147 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3148 R_PurgeTexture(s->stain );s->stain = NULL;
3149 R_PurgeTexture(s->merged);s->merged = NULL;
3150 R_PurgeTexture(s->base );s->base = NULL;
3151 R_PurgeTexture(s->pants );s->pants = NULL;
3152 R_PurgeTexture(s->shirt );s->shirt = NULL;
3153 R_PurgeTexture(s->nmap );s->nmap = NULL;
3154 R_PurgeTexture(s->gloss );s->gloss = NULL;
3155 R_PurgeTexture(s->glow );s->glow = NULL;
3156 R_PurgeTexture(s->fog );s->fog = NULL;
3157 R_PurgeTexture(s->reflect);s->reflect = NULL;
3158 s->loadsequence = 0;
3164 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3166 char basename[MAX_QPATH];
3168 Image_StripImageExtension(name, basename, sizeof(basename));
3170 if( last == NULL ) {
3172 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3173 item = r_skinframe.hash[hashindex];
3178 // linearly search through the hash bucket
3179 for( ; item ; item = item->next ) {
3180 if( !strcmp( item->basename, basename ) ) {
3187 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3191 char basename[MAX_QPATH];
3193 Image_StripImageExtension(name, basename, sizeof(basename));
3195 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3196 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3197 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3201 rtexture_t *dyntexture;
3202 // check whether its a dynamic texture
3203 dyntexture = CL_GetDynTexture( basename );
3204 if (!add && !dyntexture)
3206 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3207 memset(item, 0, sizeof(*item));
3208 strlcpy(item->basename, basename, sizeof(item->basename));
3209 item->base = dyntexture; // either NULL or dyntexture handle
3210 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3211 item->comparewidth = comparewidth;
3212 item->compareheight = compareheight;
3213 item->comparecrc = comparecrc;
3214 item->next = r_skinframe.hash[hashindex];
3215 r_skinframe.hash[hashindex] = item;
3217 else if (textureflags & TEXF_FORCE_RELOAD)
3219 rtexture_t *dyntexture;
3220 // check whether its a dynamic texture
3221 dyntexture = CL_GetDynTexture( basename );
3222 if (!add && !dyntexture)
3224 if (item->merged == item->base)
3225 item->merged = NULL;
3226 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3227 R_PurgeTexture(item->stain );item->stain = NULL;
3228 R_PurgeTexture(item->merged);item->merged = NULL;
3229 R_PurgeTexture(item->base );item->base = NULL;
3230 R_PurgeTexture(item->pants );item->pants = NULL;
3231 R_PurgeTexture(item->shirt );item->shirt = NULL;
3232 R_PurgeTexture(item->nmap );item->nmap = NULL;
3233 R_PurgeTexture(item->gloss );item->gloss = NULL;
3234 R_PurgeTexture(item->glow );item->glow = NULL;
3235 R_PurgeTexture(item->fog );item->fog = NULL;
3236 R_PurgeTexture(item->reflect);item->reflect = NULL;
3237 item->loadsequence = 0;
3239 else if( item->base == NULL )
3241 rtexture_t *dyntexture;
3242 // check whether its a dynamic texture
3243 // 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]
3244 dyntexture = CL_GetDynTexture( basename );
3245 item->base = dyntexture; // either NULL or dyntexture handle
3248 R_SkinFrame_MarkUsed(item);
3252 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3254 unsigned long long avgcolor[5], wsum; \
3262 for(pix = 0; pix < cnt; ++pix) \
3265 for(comp = 0; comp < 3; ++comp) \
3267 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3270 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3272 for(comp = 0; comp < 3; ++comp) \
3273 avgcolor[comp] += getpixel * w; \
3276 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3277 avgcolor[4] += getpixel; \
3279 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3281 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3282 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3283 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3284 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3287 extern cvar_t gl_picmip;
3288 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3291 unsigned char *pixels;
3292 unsigned char *bumppixels;
3293 unsigned char *basepixels = NULL;
3294 int basepixels_width = 0;
3295 int basepixels_height = 0;
3296 skinframe_t *skinframe;
3297 rtexture_t *ddsbase = NULL;
3298 qboolean ddshasalpha = false;
3299 float ddsavgcolor[4];
3300 char basename[MAX_QPATH];
3301 int miplevel = R_PicmipForFlags(textureflags);
3302 int savemiplevel = miplevel;
3305 if (cls.state == ca_dedicated)
3308 // return an existing skinframe if already loaded
3309 // if loading of the first image fails, don't make a new skinframe as it
3310 // would cause all future lookups of this to be missing
3311 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3312 if (skinframe && skinframe->base)
3315 Image_StripImageExtension(name, basename, sizeof(basename));
3317 // check for DDS texture file first
3318 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3320 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3321 if (basepixels == NULL)
3325 // FIXME handle miplevel
3327 if (developer_loading.integer)
3328 Con_Printf("loading skin \"%s\"\n", name);
3330 // we've got some pixels to store, so really allocate this new texture now
3332 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3333 textureflags &= ~TEXF_FORCE_RELOAD;
3334 skinframe->stain = NULL;
3335 skinframe->merged = NULL;
3336 skinframe->base = NULL;
3337 skinframe->pants = NULL;
3338 skinframe->shirt = NULL;
3339 skinframe->nmap = NULL;
3340 skinframe->gloss = NULL;
3341 skinframe->glow = NULL;
3342 skinframe->fog = NULL;
3343 skinframe->reflect = NULL;
3344 skinframe->hasalpha = false;
3348 skinframe->base = ddsbase;
3349 skinframe->hasalpha = ddshasalpha;
3350 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3351 if (r_loadfog && skinframe->hasalpha)
3352 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3353 //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]);
3357 basepixels_width = image_width;
3358 basepixels_height = image_height;
3359 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);
3360 if (textureflags & TEXF_ALPHA)
3362 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3364 if (basepixels[j] < 255)
3366 skinframe->hasalpha = true;
3370 if (r_loadfog && skinframe->hasalpha)
3372 // has transparent pixels
3373 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3374 for (j = 0;j < image_width * image_height * 4;j += 4)
3379 pixels[j+3] = basepixels[j+3];
3381 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3385 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3387 //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]);
3388 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3389 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3390 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3391 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3397 mymiplevel = savemiplevel;
3398 if (r_loadnormalmap)
3399 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3400 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3402 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3403 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3404 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3405 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3408 // _norm is the name used by tenebrae and has been adopted as standard
3409 if (r_loadnormalmap && skinframe->nmap == NULL)
3411 mymiplevel = savemiplevel;
3412 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3414 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3418 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3420 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3421 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3422 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3424 Mem_Free(bumppixels);
3426 else if (r_shadow_bumpscale_basetexture.value > 0)
3428 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3429 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3430 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3434 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3435 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3439 // _luma is supported only for tenebrae compatibility
3440 // _glow is the preferred name
3441 mymiplevel = savemiplevel;
3442 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3444 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%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);
3446 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3447 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3449 Mem_Free(pixels);pixels = NULL;
3452 mymiplevel = savemiplevel;
3453 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3455 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%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);
3457 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3458 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3464 mymiplevel = savemiplevel;
3465 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3467 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%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);
3469 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3470 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3476 mymiplevel = savemiplevel;
3477 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3479 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%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);
3481 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3482 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3488 mymiplevel = savemiplevel;
3489 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3491 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%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);
3493 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3494 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3501 Mem_Free(basepixels);
3506 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3507 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3510 unsigned char *temp1, *temp2;
3511 skinframe_t *skinframe;
3513 if (cls.state == ca_dedicated)
3516 // if already loaded just return it, otherwise make a new skinframe
3517 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3518 if (skinframe && skinframe->base)
3520 textureflags &= ~TEXF_FORCE_RELOAD;
3522 skinframe->stain = NULL;
3523 skinframe->merged = NULL;
3524 skinframe->base = NULL;
3525 skinframe->pants = NULL;
3526 skinframe->shirt = NULL;
3527 skinframe->nmap = NULL;
3528 skinframe->gloss = NULL;
3529 skinframe->glow = NULL;
3530 skinframe->fog = NULL;
3531 skinframe->reflect = NULL;
3532 skinframe->hasalpha = false;
3534 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3538 if (developer_loading.integer)
3539 Con_Printf("loading 32bit skin \"%s\"\n", name);
3541 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3543 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3544 temp2 = temp1 + width * height * 4;
3545 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3546 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3549 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3550 if (textureflags & TEXF_ALPHA)
3552 for (i = 3;i < width * height * 4;i += 4)
3554 if (skindata[i] < 255)
3556 skinframe->hasalpha = true;
3560 if (r_loadfog && skinframe->hasalpha)
3562 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3563 memcpy(fogpixels, skindata, width * height * 4);
3564 for (i = 0;i < width * height * 4;i += 4)
3565 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3566 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3567 Mem_Free(fogpixels);
3571 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3572 //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]);
3577 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3581 skinframe_t *skinframe;
3583 if (cls.state == ca_dedicated)
3586 // if already loaded just return it, otherwise make a new skinframe
3587 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3588 if (skinframe && skinframe->base)
3590 textureflags &= ~TEXF_FORCE_RELOAD;
3592 skinframe->stain = NULL;
3593 skinframe->merged = NULL;
3594 skinframe->base = NULL;
3595 skinframe->pants = NULL;
3596 skinframe->shirt = NULL;
3597 skinframe->nmap = NULL;
3598 skinframe->gloss = NULL;
3599 skinframe->glow = NULL;
3600 skinframe->fog = NULL;
3601 skinframe->reflect = NULL;
3602 skinframe->hasalpha = false;
3604 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3608 if (developer_loading.integer)
3609 Con_Printf("loading quake skin \"%s\"\n", name);
3611 // 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)
3612 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3613 memcpy(skinframe->qpixels, skindata, width*height);
3614 skinframe->qwidth = width;
3615 skinframe->qheight = height;
3618 for (i = 0;i < width * height;i++)
3619 featuresmask |= palette_featureflags[skindata[i]];
3621 skinframe->hasalpha = false;
3622 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3623 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3624 skinframe->qgeneratemerged = true;
3625 skinframe->qgeneratebase = skinframe->qhascolormapping;
3626 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3628 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3629 //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]);
3634 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3638 unsigned char *skindata;
3640 if (!skinframe->qpixels)
3643 if (!skinframe->qhascolormapping)
3644 colormapped = false;
3648 if (!skinframe->qgeneratebase)
3653 if (!skinframe->qgeneratemerged)
3657 width = skinframe->qwidth;
3658 height = skinframe->qheight;
3659 skindata = skinframe->qpixels;
3661 if (skinframe->qgeneratenmap)
3663 unsigned char *temp1, *temp2;
3664 skinframe->qgeneratenmap = false;
3665 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3666 temp2 = temp1 + width * height * 4;
3667 // use either a custom palette or the quake palette
3668 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3669 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3670 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3674 if (skinframe->qgenerateglow)
3676 skinframe->qgenerateglow = false;
3677 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3682 skinframe->qgeneratebase = false;
3683 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%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);
3684 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3685 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3689 skinframe->qgeneratemerged = false;
3690 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);
3693 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3695 Mem_Free(skinframe->qpixels);
3696 skinframe->qpixels = NULL;
3700 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)
3703 skinframe_t *skinframe;
3705 if (cls.state == ca_dedicated)
3708 // if already loaded just return it, otherwise make a new skinframe
3709 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3710 if (skinframe && skinframe->base)
3712 textureflags &= ~TEXF_FORCE_RELOAD;
3714 skinframe->stain = NULL;
3715 skinframe->merged = NULL;
3716 skinframe->base = NULL;
3717 skinframe->pants = NULL;
3718 skinframe->shirt = NULL;
3719 skinframe->nmap = NULL;
3720 skinframe->gloss = NULL;
3721 skinframe->glow = NULL;
3722 skinframe->fog = NULL;
3723 skinframe->reflect = NULL;
3724 skinframe->hasalpha = false;
3726 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3730 if (developer_loading.integer)
3731 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3733 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3734 if (textureflags & TEXF_ALPHA)
3736 for (i = 0;i < width * height;i++)
3738 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3740 skinframe->hasalpha = true;
3744 if (r_loadfog && skinframe->hasalpha)
3745 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3748 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3749 //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]);
3754 skinframe_t *R_SkinFrame_LoadMissing(void)
3756 skinframe_t *skinframe;
3758 if (cls.state == ca_dedicated)
3761 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3762 skinframe->stain = NULL;
3763 skinframe->merged = NULL;
3764 skinframe->base = NULL;
3765 skinframe->pants = NULL;
3766 skinframe->shirt = NULL;
3767 skinframe->nmap = NULL;
3768 skinframe->gloss = NULL;
3769 skinframe->glow = NULL;
3770 skinframe->fog = NULL;
3771 skinframe->reflect = NULL;
3772 skinframe->hasalpha = false;
3774 skinframe->avgcolor[0] = rand() / RAND_MAX;
3775 skinframe->avgcolor[1] = rand() / RAND_MAX;
3776 skinframe->avgcolor[2] = rand() / RAND_MAX;
3777 skinframe->avgcolor[3] = 1;
3782 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3783 typedef struct suffixinfo_s
3786 qboolean flipx, flipy, flipdiagonal;
3789 static suffixinfo_t suffix[3][6] =
3792 {"px", false, false, false},
3793 {"nx", false, false, false},
3794 {"py", false, false, false},
3795 {"ny", false, false, false},
3796 {"pz", false, false, false},
3797 {"nz", false, false, false}
3800 {"posx", false, false, false},
3801 {"negx", false, false, false},
3802 {"posy", false, false, false},
3803 {"negy", false, false, false},
3804 {"posz", false, false, false},
3805 {"negz", false, false, false}
3808 {"rt", true, false, true},
3809 {"lf", false, true, true},
3810 {"ft", true, true, false},
3811 {"bk", false, false, false},
3812 {"up", true, false, true},
3813 {"dn", true, false, true}
3817 static int componentorder[4] = {0, 1, 2, 3};
3819 rtexture_t *R_LoadCubemap(const char *basename)
3821 int i, j, cubemapsize;
3822 unsigned char *cubemappixels, *image_buffer;
3823 rtexture_t *cubemaptexture;
3825 // must start 0 so the first loadimagepixels has no requested width/height
3827 cubemappixels = NULL;
3828 cubemaptexture = NULL;
3829 // keep trying different suffix groups (posx, px, rt) until one loads
3830 for (j = 0;j < 3 && !cubemappixels;j++)
3832 // load the 6 images in the suffix group
3833 for (i = 0;i < 6;i++)
3835 // generate an image name based on the base and and suffix
3836 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3838 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3840 // an image loaded, make sure width and height are equal
3841 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3843 // if this is the first image to load successfully, allocate the cubemap memory
3844 if (!cubemappixels && image_width >= 1)
3846 cubemapsize = image_width;
3847 // note this clears to black, so unavailable sides are black
3848 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3850 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3852 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);
3855 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3857 Mem_Free(image_buffer);
3861 // if a cubemap loaded, upload it
3864 if (developer_loading.integer)
3865 Con_Printf("loading cubemap \"%s\"\n", basename);
3867 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);
3868 Mem_Free(cubemappixels);
3872 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3873 if (developer_loading.integer)
3875 Con_Printf("(tried tried images ");
3876 for (j = 0;j < 3;j++)
3877 for (i = 0;i < 6;i++)
3878 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3879 Con_Print(" and was unable to find any of them).\n");
3882 return cubemaptexture;
3885 rtexture_t *R_GetCubemap(const char *basename)
3888 for (i = 0;i < r_texture_numcubemaps;i++)
3889 if (r_texture_cubemaps[i] != NULL)
3890 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3891 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3892 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3893 return r_texture_whitecube;
3894 r_texture_numcubemaps++;
3895 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3896 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3897 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3898 return r_texture_cubemaps[i]->texture;
3901 void R_FreeCubemap(const char *basename)
3905 for (i = 0;i < r_texture_numcubemaps;i++)
3907 if (r_texture_cubemaps[i] != NULL)
3909 if (r_texture_cubemaps[i]->texture)
3911 if (developer_loading.integer)
3912 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3913 R_FreeTexture(r_texture_cubemaps[i]->texture);
3914 Mem_Free(r_texture_cubemaps[i]);
3915 r_texture_cubemaps[i] = NULL;
3921 void R_FreeCubemaps(void)
3924 for (i = 0;i < r_texture_numcubemaps;i++)
3926 if (developer_loading.integer)
3927 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3928 if (r_texture_cubemaps[i] != NULL)
3930 if (r_texture_cubemaps[i]->texture)
3931 R_FreeTexture(r_texture_cubemaps[i]->texture);
3932 Mem_Free(r_texture_cubemaps[i]);
3935 r_texture_numcubemaps = 0;
3938 void R_Main_FreeViewCache(void)
3940 if (r_refdef.viewcache.entityvisible)
3941 Mem_Free(r_refdef.viewcache.entityvisible);
3942 if (r_refdef.viewcache.world_pvsbits)
3943 Mem_Free(r_refdef.viewcache.world_pvsbits);
3944 if (r_refdef.viewcache.world_leafvisible)
3945 Mem_Free(r_refdef.viewcache.world_leafvisible);
3946 if (r_refdef.viewcache.world_surfacevisible)
3947 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3948 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3951 void R_Main_ResizeViewCache(void)
3953 int numentities = r_refdef.scene.numentities;
3954 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3955 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3956 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3957 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3958 if (r_refdef.viewcache.maxentities < numentities)
3960 r_refdef.viewcache.maxentities = numentities;
3961 if (r_refdef.viewcache.entityvisible)
3962 Mem_Free(r_refdef.viewcache.entityvisible);
3963 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3965 if (r_refdef.viewcache.world_numclusters != numclusters)
3967 r_refdef.viewcache.world_numclusters = numclusters;
3968 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3969 if (r_refdef.viewcache.world_pvsbits)
3970 Mem_Free(r_refdef.viewcache.world_pvsbits);
3971 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3973 if (r_refdef.viewcache.world_numleafs != numleafs)
3975 r_refdef.viewcache.world_numleafs = numleafs;
3976 if (r_refdef.viewcache.world_leafvisible)
3977 Mem_Free(r_refdef.viewcache.world_leafvisible);
3978 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3980 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3982 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3983 if (r_refdef.viewcache.world_surfacevisible)
3984 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3985 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3989 extern rtexture_t *loadingscreentexture;
3990 void gl_main_start(void)
3992 loadingscreentexture = NULL;
3993 r_texture_blanknormalmap = NULL;
3994 r_texture_white = NULL;
3995 r_texture_grey128 = NULL;
3996 r_texture_black = NULL;
3997 r_texture_whitecube = NULL;
3998 r_texture_normalizationcube = NULL;
3999 r_texture_fogattenuation = NULL;
4000 r_texture_fogheighttexture = NULL;
4001 r_texture_gammaramps = NULL;
4002 r_texture_numcubemaps = 0;
4004 r_loaddds = r_texture_dds_load.integer != 0;
4005 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4007 switch(vid.renderpath)
4009 case RENDERPATH_GL20:
4010 case RENDERPATH_D3D9:
4011 case RENDERPATH_D3D10:
4012 case RENDERPATH_D3D11:
4013 case RENDERPATH_SOFT:
4014 case RENDERPATH_GLES2:
4015 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4016 Cvar_SetValueQuick(&gl_combine, 1);
4017 Cvar_SetValueQuick(&r_glsl, 1);
4018 r_loadnormalmap = true;
4022 case RENDERPATH_GL13:
4023 case RENDERPATH_GLES1:
4024 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4025 Cvar_SetValueQuick(&gl_combine, 1);
4026 Cvar_SetValueQuick(&r_glsl, 0);
4027 r_loadnormalmap = false;
4028 r_loadgloss = false;
4031 case RENDERPATH_GL11:
4032 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4033 Cvar_SetValueQuick(&gl_combine, 0);
4034 Cvar_SetValueQuick(&r_glsl, 0);
4035 r_loadnormalmap = false;
4036 r_loadgloss = false;
4042 R_FrameData_Reset();
4046 memset(r_queries, 0, sizeof(r_queries));
4048 r_qwskincache = NULL;
4049 r_qwskincache_size = 0;
4051 // due to caching of texture_t references, the collision cache must be reset
4052 Collision_Cache_Reset(true);
4054 // set up r_skinframe loading system for textures
4055 memset(&r_skinframe, 0, sizeof(r_skinframe));
4056 r_skinframe.loadsequence = 1;
4057 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4059 r_main_texturepool = R_AllocTexturePool();
4060 R_BuildBlankTextures();
4062 if (vid.support.arb_texture_cube_map)
4065 R_BuildNormalizationCube();
4067 r_texture_fogattenuation = NULL;
4068 r_texture_fogheighttexture = NULL;
4069 r_texture_gammaramps = NULL;
4070 //r_texture_fogintensity = NULL;
4071 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4072 memset(&r_waterstate, 0, sizeof(r_waterstate));
4073 r_glsl_permutation = NULL;
4074 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4075 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4076 glslshaderstring = NULL;
4078 r_hlsl_permutation = NULL;
4079 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4080 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4082 hlslshaderstring = NULL;
4083 memset(&r_svbsp, 0, sizeof (r_svbsp));
4085 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4086 r_texture_numcubemaps = 0;
4088 r_refdef.fogmasktable_density = 0;
4091 void gl_main_shutdown(void)
4094 R_FrameData_Reset();
4096 R_Main_FreeViewCache();
4098 switch(vid.renderpath)
4100 case RENDERPATH_GL11:
4101 case RENDERPATH_GL13:
4102 case RENDERPATH_GL20:
4103 case RENDERPATH_GLES1:
4104 case RENDERPATH_GLES2:
4105 #ifdef GL_SAMPLES_PASSED_ARB
4107 qglDeleteQueriesARB(r_maxqueries, r_queries);
4110 case RENDERPATH_D3D9:
4111 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4113 case RENDERPATH_D3D10:
4114 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4116 case RENDERPATH_D3D11:
4117 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4119 case RENDERPATH_SOFT:
4125 memset(r_queries, 0, sizeof(r_queries));
4127 r_qwskincache = NULL;
4128 r_qwskincache_size = 0;
4130 // clear out the r_skinframe state
4131 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4132 memset(&r_skinframe, 0, sizeof(r_skinframe));
4135 Mem_Free(r_svbsp.nodes);
4136 memset(&r_svbsp, 0, sizeof (r_svbsp));
4137 R_FreeTexturePool(&r_main_texturepool);
4138 loadingscreentexture = NULL;
4139 r_texture_blanknormalmap = NULL;
4140 r_texture_white = NULL;
4141 r_texture_grey128 = NULL;
4142 r_texture_black = NULL;
4143 r_texture_whitecube = NULL;
4144 r_texture_normalizationcube = NULL;
4145 r_texture_fogattenuation = NULL;
4146 r_texture_fogheighttexture = NULL;
4147 r_texture_gammaramps = NULL;
4148 r_texture_numcubemaps = 0;
4149 //r_texture_fogintensity = NULL;
4150 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4151 memset(&r_waterstate, 0, sizeof(r_waterstate));
4154 r_glsl_permutation = NULL;
4155 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4156 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4157 glslshaderstring = NULL;
4159 r_hlsl_permutation = NULL;
4160 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4161 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4163 hlslshaderstring = NULL;
4166 extern void CL_ParseEntityLump(char *entitystring);
4167 void gl_main_newmap(void)
4169 // FIXME: move this code to client
4170 char *entities, entname[MAX_QPATH];
4172 Mem_Free(r_qwskincache);
4173 r_qwskincache = NULL;
4174 r_qwskincache_size = 0;
4177 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4178 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4180 CL_ParseEntityLump(entities);
4184 if (cl.worldmodel->brush.entities)
4185 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4187 R_Main_FreeViewCache();
4189 R_FrameData_Reset();
4192 void GL_Main_Init(void)
4194 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4196 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4197 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4198 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4199 if (gamemode == GAME_NEHAHRA)
4201 Cvar_RegisterVariable (&gl_fogenable);
4202 Cvar_RegisterVariable (&gl_fogdensity);
4203 Cvar_RegisterVariable (&gl_fogred);
4204 Cvar_RegisterVariable (&gl_foggreen);
4205 Cvar_RegisterVariable (&gl_fogblue);
4206 Cvar_RegisterVariable (&gl_fogstart);
4207 Cvar_RegisterVariable (&gl_fogend);
4208 Cvar_RegisterVariable (&gl_skyclip);
4210 Cvar_RegisterVariable(&r_motionblur);
4211 Cvar_RegisterVariable(&r_damageblur);
4212 Cvar_RegisterVariable(&r_motionblur_averaging);
4213 Cvar_RegisterVariable(&r_motionblur_randomize);
4214 Cvar_RegisterVariable(&r_motionblur_minblur);
4215 Cvar_RegisterVariable(&r_motionblur_maxblur);
4216 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4217 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4218 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4219 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4220 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4221 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4222 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4223 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4224 Cvar_RegisterVariable(&r_equalize_entities_by);
4225 Cvar_RegisterVariable(&r_equalize_entities_to);
4226 Cvar_RegisterVariable(&r_depthfirst);
4227 Cvar_RegisterVariable(&r_useinfinitefarclip);
4228 Cvar_RegisterVariable(&r_farclip_base);
4229 Cvar_RegisterVariable(&r_farclip_world);
4230 Cvar_RegisterVariable(&r_nearclip);
4231 Cvar_RegisterVariable(&r_deformvertexes);
4232 Cvar_RegisterVariable(&r_transparent);
4233 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4234 Cvar_RegisterVariable(&r_showoverdraw);
4235 Cvar_RegisterVariable(&r_showbboxes);
4236 Cvar_RegisterVariable(&r_showsurfaces);
4237 Cvar_RegisterVariable(&r_showtris);
4238 Cvar_RegisterVariable(&r_shownormals);
4239 Cvar_RegisterVariable(&r_showlighting);
4240 Cvar_RegisterVariable(&r_showshadowvolumes);
4241 Cvar_RegisterVariable(&r_showcollisionbrushes);
4242 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4243 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4244 Cvar_RegisterVariable(&r_showdisabledepthtest);
4245 Cvar_RegisterVariable(&r_drawportals);
4246 Cvar_RegisterVariable(&r_drawentities);
4247 Cvar_RegisterVariable(&r_draw2d);
4248 Cvar_RegisterVariable(&r_drawworld);
4249 Cvar_RegisterVariable(&r_cullentities_trace);
4250 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4251 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4252 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4253 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4254 Cvar_RegisterVariable(&r_sortentities);
4255 Cvar_RegisterVariable(&r_drawviewmodel);
4256 Cvar_RegisterVariable(&r_drawexteriormodel);
4257 Cvar_RegisterVariable(&r_speeds);
4258 Cvar_RegisterVariable(&r_fullbrights);
4259 Cvar_RegisterVariable(&r_wateralpha);
4260 Cvar_RegisterVariable(&r_dynamic);
4261 Cvar_RegisterVariable(&r_fakelight);
4262 Cvar_RegisterVariable(&r_fakelight_intensity);
4263 Cvar_RegisterVariable(&r_fullbright);
4264 Cvar_RegisterVariable(&r_shadows);
4265 Cvar_RegisterVariable(&r_shadows_darken);
4266 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4267 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4268 Cvar_RegisterVariable(&r_shadows_throwdistance);
4269 Cvar_RegisterVariable(&r_shadows_throwdirection);
4270 Cvar_RegisterVariable(&r_shadows_focus);
4271 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4272 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4273 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4274 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4275 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4276 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4277 Cvar_RegisterVariable(&r_fog_exp2);
4278 Cvar_RegisterVariable(&r_fog_clear);
4279 Cvar_RegisterVariable(&r_drawfog);
4280 Cvar_RegisterVariable(&r_transparentdepthmasking);
4281 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4282 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4283 Cvar_RegisterVariable(&r_texture_dds_load);
4284 Cvar_RegisterVariable(&r_texture_dds_save);
4285 Cvar_RegisterVariable(&r_textureunits);
4286 Cvar_RegisterVariable(&gl_combine);
4287 Cvar_RegisterVariable(&r_viewfbo);
4288 Cvar_RegisterVariable(&r_viewscale);
4289 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4290 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4291 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4292 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4293 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4294 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4295 Cvar_RegisterVariable(&r_glsl);
4296 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4297 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4298 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4299 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4300 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4301 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4302 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4303 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4304 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4305 Cvar_RegisterVariable(&r_glsl_postprocess);
4306 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4307 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4308 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4309 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4310 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4311 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4312 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4313 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4315 Cvar_RegisterVariable(&r_water);
4316 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4317 Cvar_RegisterVariable(&r_water_clippingplanebias);
4318 Cvar_RegisterVariable(&r_water_refractdistort);
4319 Cvar_RegisterVariable(&r_water_reflectdistort);
4320 Cvar_RegisterVariable(&r_water_scissormode);
4321 Cvar_RegisterVariable(&r_water_lowquality);
4323 Cvar_RegisterVariable(&r_lerpsprites);
4324 Cvar_RegisterVariable(&r_lerpmodels);
4325 Cvar_RegisterVariable(&r_lerplightstyles);
4326 Cvar_RegisterVariable(&r_waterscroll);
4327 Cvar_RegisterVariable(&r_bloom);
4328 Cvar_RegisterVariable(&r_bloom_colorscale);
4329 Cvar_RegisterVariable(&r_bloom_brighten);
4330 Cvar_RegisterVariable(&r_bloom_blur);
4331 Cvar_RegisterVariable(&r_bloom_resolution);
4332 Cvar_RegisterVariable(&r_bloom_colorexponent);
4333 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4334 Cvar_RegisterVariable(&r_hdr);
4335 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4336 Cvar_RegisterVariable(&r_hdr_glowintensity);
4337 Cvar_RegisterVariable(&r_hdr_range);
4338 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4339 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4340 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4341 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4342 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4343 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4344 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4345 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4346 Cvar_RegisterVariable(&developer_texturelogging);
4347 Cvar_RegisterVariable(&gl_lightmaps);
4348 Cvar_RegisterVariable(&r_test);
4349 Cvar_RegisterVariable(&r_glsl_saturation);
4350 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4351 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4352 Cvar_RegisterVariable(&r_framedatasize);
4353 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4354 Cvar_SetValue("r_fullbrights", 0);
4355 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4358 extern void R_Textures_Init(void);
4359 extern void GL_Draw_Init(void);
4360 extern void GL_Main_Init(void);
4361 extern void R_Shadow_Init(void);
4362 extern void R_Sky_Init(void);
4363 extern void GL_Surf_Init(void);
4364 extern void R_Particles_Init(void);
4365 extern void R_Explosion_Init(void);
4366 extern void gl_backend_init(void);
4367 extern void Sbar_Init(void);
4368 extern void R_LightningBeams_Init(void);
4369 extern void Mod_RenderInit(void);
4370 extern void Font_Init(void);
4372 void Render_Init(void)
4385 R_LightningBeams_Init();
4395 extern char *ENGINE_EXTENSIONS;
4398 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4399 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4400 gl_version = (const char *)qglGetString(GL_VERSION);
4401 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4405 if (!gl_platformextensions)
4406 gl_platformextensions = "";
4408 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4409 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4410 Con_Printf("GL_VERSION: %s\n", gl_version);
4411 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4412 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4414 VID_CheckExtensions();
4416 // LordHavoc: report supported extensions
4417 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4419 // clear to black (loading plaque will be seen over this)
4420 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4424 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4428 if (r_trippy.integer)
4430 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4432 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4435 p = r_refdef.view.frustum + i;
4440 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4444 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4448 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4452 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4456 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4460 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4464 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4468 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4476 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4480 if (r_trippy.integer)
4482 for (i = 0;i < numplanes;i++)
4489 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4493 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4497 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4501 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4505 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4509 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4513 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4517 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4525 //==================================================================================
4527 // LordHavoc: this stores temporary data used within the same frame
4529 typedef struct r_framedata_mem_s
4531 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4532 size_t size; // how much usable space
4533 size_t current; // how much space in use
4534 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4535 size_t wantedsize; // how much space was allocated
4536 unsigned char *data; // start of real data (16byte aligned)
4540 static r_framedata_mem_t *r_framedata_mem;
4542 void R_FrameData_Reset(void)
4544 while (r_framedata_mem)
4546 r_framedata_mem_t *next = r_framedata_mem->purge;
4547 Mem_Free(r_framedata_mem);
4548 r_framedata_mem = next;
4552 void R_FrameData_Resize(void)
4555 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4556 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4557 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4559 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4560 newmem->wantedsize = wantedsize;
4561 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4562 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4563 newmem->current = 0;
4565 newmem->purge = r_framedata_mem;
4566 r_framedata_mem = newmem;
4570 void R_FrameData_NewFrame(void)
4572 R_FrameData_Resize();
4573 if (!r_framedata_mem)
4575 // if we ran out of space on the last frame, free the old memory now
4576 while (r_framedata_mem->purge)
4578 // repeatedly remove the second item in the list, leaving only head
4579 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4580 Mem_Free(r_framedata_mem->purge);
4581 r_framedata_mem->purge = next;
4583 // reset the current mem pointer
4584 r_framedata_mem->current = 0;
4585 r_framedata_mem->mark = 0;
4588 void *R_FrameData_Alloc(size_t size)
4592 // align to 16 byte boundary - the data pointer is already aligned, so we
4593 // only need to ensure the size of every allocation is also aligned
4594 size = (size + 15) & ~15;
4596 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4598 // emergency - we ran out of space, allocate more memory
4599 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4600 R_FrameData_Resize();
4603 data = r_framedata_mem->data + r_framedata_mem->current;
4604 r_framedata_mem->current += size;
4606 // count the usage for stats
4607 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4608 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4610 return (void *)data;
4613 void *R_FrameData_Store(size_t size, void *data)
4615 void *d = R_FrameData_Alloc(size);
4617 memcpy(d, data, size);
4621 void R_FrameData_SetMark(void)
4623 if (!r_framedata_mem)
4625 r_framedata_mem->mark = r_framedata_mem->current;
4628 void R_FrameData_ReturnToMark(void)
4630 if (!r_framedata_mem)
4632 r_framedata_mem->current = r_framedata_mem->mark;
4635 //==================================================================================
4637 // LordHavoc: animcache originally written by Echon, rewritten since then
4640 * Animation cache prevents re-generating mesh data for an animated model
4641 * multiple times in one frame for lighting, shadowing, reflections, etc.
4644 void R_AnimCache_Free(void)
4648 void R_AnimCache_ClearCache(void)
4651 entity_render_t *ent;
4653 for (i = 0;i < r_refdef.scene.numentities;i++)
4655 ent = r_refdef.scene.entities[i];
4656 ent->animcache_vertex3f = NULL;
4657 ent->animcache_normal3f = NULL;
4658 ent->animcache_svector3f = NULL;
4659 ent->animcache_tvector3f = NULL;
4660 ent->animcache_vertexmesh = NULL;
4661 ent->animcache_vertex3fbuffer = NULL;
4662 ent->animcache_vertexmeshbuffer = NULL;
4666 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4670 // check if we need the meshbuffers
4671 if (!vid.useinterleavedarrays)
4674 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4675 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4676 // TODO: upload vertex3f buffer?
4677 if (ent->animcache_vertexmesh)
4679 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4680 for (i = 0;i < numvertices;i++)
4681 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4682 if (ent->animcache_svector3f)
4683 for (i = 0;i < numvertices;i++)
4684 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4685 if (ent->animcache_tvector3f)
4686 for (i = 0;i < numvertices;i++)
4687 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4688 if (ent->animcache_normal3f)
4689 for (i = 0;i < numvertices;i++)
4690 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4691 // TODO: upload vertexmeshbuffer?
4695 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4697 dp_model_t *model = ent->model;
4699 // see if it's already cached this frame
4700 if (ent->animcache_vertex3f)
4702 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4703 if (wantnormals || wanttangents)
4705 if (ent->animcache_normal3f)
4706 wantnormals = false;
4707 if (ent->animcache_svector3f)
4708 wanttangents = false;
4709 if (wantnormals || wanttangents)
4711 numvertices = model->surfmesh.num_vertices;
4713 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4716 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4717 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4719 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4720 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4726 // see if this ent is worth caching
4727 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4729 // get some memory for this entity and generate mesh data
4730 numvertices = model->surfmesh.num_vertices;
4731 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4733 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4736 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4737 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4739 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4740 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4745 void R_AnimCache_CacheVisibleEntities(void)
4748 qboolean wantnormals = true;
4749 qboolean wanttangents = !r_showsurfaces.integer;
4751 switch(vid.renderpath)
4753 case RENDERPATH_GL20:
4754 case RENDERPATH_D3D9:
4755 case RENDERPATH_D3D10:
4756 case RENDERPATH_D3D11:
4757 case RENDERPATH_GLES2:
4759 case RENDERPATH_GL11:
4760 case RENDERPATH_GL13:
4761 case RENDERPATH_GLES1:
4762 wanttangents = false;
4764 case RENDERPATH_SOFT:
4768 if (r_shownormals.integer)
4769 wanttangents = wantnormals = true;
4771 // TODO: thread this
4772 // NOTE: R_PrepareRTLights() also caches entities
4774 for (i = 0;i < r_refdef.scene.numentities;i++)
4775 if (r_refdef.viewcache.entityvisible[i])
4776 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4779 //==================================================================================
4781 extern cvar_t r_overheadsprites_pushback;
4783 static void R_View_UpdateEntityLighting (void)
4786 entity_render_t *ent;
4787 vec3_t tempdiffusenormal, avg;
4788 vec_t f, fa, fd, fdd;
4789 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4791 for (i = 0;i < r_refdef.scene.numentities;i++)
4793 ent = r_refdef.scene.entities[i];
4795 // skip unseen models
4796 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4800 if (ent->model && ent->model->brush.num_leafs)
4802 // TODO: use modellight for r_ambient settings on world?
4803 VectorSet(ent->modellight_ambient, 0, 0, 0);
4804 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4805 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4809 // fetch the lighting from the worldmodel data
4810 VectorClear(ent->modellight_ambient);
4811 VectorClear(ent->modellight_diffuse);
4812 VectorClear(tempdiffusenormal);
4813 if (ent->flags & RENDER_LIGHT)
4816 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4818 // complete lightning for lit sprites
4819 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4820 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4822 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4823 org[2] = org[2] + r_overheadsprites_pushback.value;
4824 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4827 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4829 if(ent->flags & RENDER_EQUALIZE)
4831 // first fix up ambient lighting...
4832 if(r_equalize_entities_minambient.value > 0)
4834 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4837 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4838 if(fa < r_equalize_entities_minambient.value * fd)
4841 // fa'/fd' = minambient
4842 // fa'+0.25*fd' = fa+0.25*fd
4844 // fa' = fd' * minambient
4845 // fd'*(0.25+minambient) = fa+0.25*fd
4847 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4848 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4850 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4851 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
4852 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4853 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4858 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4860 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4861 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4865 // adjust brightness and saturation to target
4866 avg[0] = avg[1] = avg[2] = fa / f;
4867 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4868 avg[0] = avg[1] = avg[2] = fd / f;
4869 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4875 VectorSet(ent->modellight_ambient, 1, 1, 1);
4877 // move the light direction into modelspace coordinates for lighting code
4878 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4879 if(VectorLength2(ent->modellight_lightdir) == 0)
4880 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4881 VectorNormalize(ent->modellight_lightdir);
4885 #define MAX_LINEOFSIGHTTRACES 64
4887 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4890 vec3_t boxmins, boxmaxs;
4893 dp_model_t *model = r_refdef.scene.worldmodel;
4895 if (!model || !model->brush.TraceLineOfSight)
4898 // expand the box a little
4899 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4900 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4901 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4902 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4903 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4904 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4906 // return true if eye is inside enlarged box
4907 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4911 VectorCopy(eye, start);
4912 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4913 if (model->brush.TraceLineOfSight(model, start, end))
4916 // try various random positions
4917 for (i = 0;i < numsamples;i++)
4919 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4920 if (model->brush.TraceLineOfSight(model, start, end))
4928 static void R_View_UpdateEntityVisible (void)
4933 entity_render_t *ent;
4935 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4936 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4937 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4938 : RENDER_EXTERIORMODEL;
4939 if (!r_drawviewmodel.integer)
4940 renderimask |= RENDER_VIEWMODEL;
4941 if (!r_drawexteriormodel.integer)
4942 renderimask |= RENDER_EXTERIORMODEL;
4943 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4945 // worldmodel can check visibility
4946 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4947 for (i = 0;i < r_refdef.scene.numentities;i++)
4949 ent = r_refdef.scene.entities[i];
4950 if (!(ent->flags & renderimask))
4951 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)))
4952 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4953 r_refdef.viewcache.entityvisible[i] = true;
4958 // no worldmodel or it can't check visibility
4959 for (i = 0;i < r_refdef.scene.numentities;i++)
4961 ent = r_refdef.scene.entities[i];
4962 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4965 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4966 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4968 for (i = 0;i < r_refdef.scene.numentities;i++)
4970 if (!r_refdef.viewcache.entityvisible[i])
4972 ent = r_refdef.scene.entities[i];
4973 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4975 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4977 continue; // temp entities do pvs only
4978 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4979 ent->last_trace_visibility = realtime;
4980 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4981 r_refdef.viewcache.entityvisible[i] = 0;
4987 /// only used if skyrendermasked, and normally returns false
4988 int R_DrawBrushModelsSky (void)
4991 entity_render_t *ent;
4994 for (i = 0;i < r_refdef.scene.numentities;i++)
4996 if (!r_refdef.viewcache.entityvisible[i])
4998 ent = r_refdef.scene.entities[i];
4999 if (!ent->model || !ent->model->DrawSky)
5001 ent->model->DrawSky(ent);
5007 static void R_DrawNoModel(entity_render_t *ent);
5008 static void R_DrawModels(void)
5011 entity_render_t *ent;
5013 for (i = 0;i < r_refdef.scene.numentities;i++)
5015 if (!r_refdef.viewcache.entityvisible[i])
5017 ent = r_refdef.scene.entities[i];
5018 r_refdef.stats.entities++;
5020 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5023 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5024 Con_Printf("R_DrawModels\n");
5025 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]);
5026 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);
5027 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);
5030 if (ent->model && ent->model->Draw != NULL)
5031 ent->model->Draw(ent);
5037 static void R_DrawModelsDepth(void)
5040 entity_render_t *ent;
5042 for (i = 0;i < r_refdef.scene.numentities;i++)
5044 if (!r_refdef.viewcache.entityvisible[i])
5046 ent = r_refdef.scene.entities[i];
5047 if (ent->model && ent->model->DrawDepth != NULL)
5048 ent->model->DrawDepth(ent);
5052 static void R_DrawModelsDebug(void)
5055 entity_render_t *ent;
5057 for (i = 0;i < r_refdef.scene.numentities;i++)
5059 if (!r_refdef.viewcache.entityvisible[i])
5061 ent = r_refdef.scene.entities[i];
5062 if (ent->model && ent->model->DrawDebug != NULL)
5063 ent->model->DrawDebug(ent);
5067 static void R_DrawModelsAddWaterPlanes(void)
5070 entity_render_t *ent;
5072 for (i = 0;i < r_refdef.scene.numentities;i++)
5074 if (!r_refdef.viewcache.entityvisible[i])
5076 ent = r_refdef.scene.entities[i];
5077 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5078 ent->model->DrawAddWaterPlanes(ent);
5082 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5084 if (r_hdr_irisadaptation.integer)
5088 vec3_t diffusenormal;
5092 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5093 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5094 brightness = max(0.0000001f, brightness);
5095 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5096 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5097 current = r_hdr_irisadaptation_value.value;
5099 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5100 else if (current > goal)
5101 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5102 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5103 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5105 else if (r_hdr_irisadaptation_value.value != 1.0f)
5106 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5109 static void R_View_SetFrustum(const int *scissor)
5112 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5113 vec3_t forward, left, up, origin, v;
5117 // flipped x coordinates (because x points left here)
5118 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5119 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5121 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5122 switch(vid.renderpath)
5124 case RENDERPATH_D3D9:
5125 case RENDERPATH_D3D10:
5126 case RENDERPATH_D3D11:
5127 // non-flipped y coordinates
5128 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5129 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5131 case RENDERPATH_SOFT:
5132 case RENDERPATH_GL11:
5133 case RENDERPATH_GL13:
5134 case RENDERPATH_GL20:
5135 case RENDERPATH_GLES1:
5136 case RENDERPATH_GLES2:
5137 // non-flipped y coordinates
5138 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5139 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5144 // we can't trust r_refdef.view.forward and friends in reflected scenes
5145 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5148 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5149 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5150 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5151 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5152 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5153 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5154 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5155 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5156 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5157 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5158 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5159 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5163 zNear = r_refdef.nearclip;
5164 nudge = 1.0 - 1.0 / (1<<23);
5165 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5166 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5167 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5168 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5169 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5170 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5171 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5172 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5178 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5179 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5180 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5181 r_refdef.view.frustum[0].dist = m[15] - m[12];
5183 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5184 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5185 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5186 r_refdef.view.frustum[1].dist = m[15] + m[12];
5188 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5189 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5190 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5191 r_refdef.view.frustum[2].dist = m[15] - m[13];
5193 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5194 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5195 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5196 r_refdef.view.frustum[3].dist = m[15] + m[13];
5198 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5199 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5200 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5201 r_refdef.view.frustum[4].dist = m[15] - m[14];
5203 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5204 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5205 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5206 r_refdef.view.frustum[5].dist = m[15] + m[14];
5209 if (r_refdef.view.useperspective)
5211 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5212 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]);
5213 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]);
5214 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]);
5215 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]);
5217 // then the normals from the corners relative to origin
5218 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5219 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5220 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5221 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5223 // in a NORMAL view, forward cross left == up
5224 // in a REFLECTED view, forward cross left == down
5225 // so our cross products above need to be adjusted for a left handed coordinate system
5226 CrossProduct(forward, left, v);
5227 if(DotProduct(v, up) < 0)
5229 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5230 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5231 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5232 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5235 // Leaving those out was a mistake, those were in the old code, and they
5236 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5237 // I couldn't reproduce it after adding those normalizations. --blub
5238 VectorNormalize(r_refdef.view.frustum[0].normal);
5239 VectorNormalize(r_refdef.view.frustum[1].normal);
5240 VectorNormalize(r_refdef.view.frustum[2].normal);
5241 VectorNormalize(r_refdef.view.frustum[3].normal);
5243 // make the corners absolute
5244 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5245 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5246 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5247 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5250 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5252 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5253 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5254 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5255 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5256 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5260 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5261 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5262 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5263 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5264 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5265 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5266 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5267 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5268 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5269 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5271 r_refdef.view.numfrustumplanes = 5;
5273 if (r_refdef.view.useclipplane)
5275 r_refdef.view.numfrustumplanes = 6;
5276 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5279 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5280 PlaneClassify(r_refdef.view.frustum + i);
5282 // LordHavoc: note to all quake engine coders, Quake had a special case
5283 // for 90 degrees which assumed a square view (wrong), so I removed it,
5284 // Quake2 has it disabled as well.
5286 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5287 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5288 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5289 //PlaneClassify(&frustum[0]);
5291 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5292 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5293 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5294 //PlaneClassify(&frustum[1]);
5296 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5297 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5298 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5299 //PlaneClassify(&frustum[2]);
5301 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5302 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5303 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5304 //PlaneClassify(&frustum[3]);
5307 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5308 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5309 //PlaneClassify(&frustum[4]);
5312 void R_View_UpdateWithScissor(const int *myscissor)
5314 R_Main_ResizeViewCache();
5315 R_View_SetFrustum(myscissor);
5316 R_View_WorldVisibility(r_refdef.view.useclipplane);
5317 R_View_UpdateEntityVisible();
5318 R_View_UpdateEntityLighting();
5321 void R_View_Update(void)
5323 R_Main_ResizeViewCache();
5324 R_View_SetFrustum(NULL);
5325 R_View_WorldVisibility(r_refdef.view.useclipplane);
5326 R_View_UpdateEntityVisible();
5327 R_View_UpdateEntityLighting();
5330 float viewscalefpsadjusted = 1.0f;
5332 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5334 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5335 scale = bound(0.03125f, scale, 1.0f);
5336 *outwidth = (int)ceil(width * scale);
5337 *outheight = (int)ceil(height * scale);
5340 void R_Mesh_SetMainRenderTargets(void)
5342 if (r_bloomstate.fbo_framebuffer)
5343 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5345 R_Mesh_ResetRenderTargets();
5348 void R_SetupView(qboolean allowwaterclippingplane)
5350 const float *customclipplane = NULL;
5352 int scaledwidth, scaledheight;
5353 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5355 // LordHavoc: couldn't figure out how to make this approach the
5356 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5357 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5358 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5359 dist = r_refdef.view.clipplane.dist;
5360 plane[0] = r_refdef.view.clipplane.normal[0];
5361 plane[1] = r_refdef.view.clipplane.normal[1];
5362 plane[2] = r_refdef.view.clipplane.normal[2];
5364 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5367 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5368 if (!r_refdef.view.useperspective)
5369 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - 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);
5370 else if (vid.stencil && r_useinfinitefarclip.integer)
5371 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5373 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5374 R_Mesh_SetMainRenderTargets();
5375 R_SetViewport(&r_refdef.view.viewport);
5376 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5378 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5379 float screenplane[4];
5380 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5381 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5382 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5383 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5384 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5388 void R_EntityMatrix(const matrix4x4_t *matrix)
5390 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5392 gl_modelmatrixchanged = false;
5393 gl_modelmatrix = *matrix;
5394 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5395 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5396 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5397 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5399 switch(vid.renderpath)
5401 case RENDERPATH_D3D9:
5403 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5404 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5407 case RENDERPATH_D3D10:
5408 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5410 case RENDERPATH_D3D11:
5411 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5413 case RENDERPATH_GL11:
5414 case RENDERPATH_GL13:
5415 case RENDERPATH_GLES1:
5416 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5418 case RENDERPATH_SOFT:
5419 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5420 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5422 case RENDERPATH_GL20:
5423 case RENDERPATH_GLES2:
5424 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5425 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5431 void R_ResetViewRendering2D(void)
5433 r_viewport_t viewport;
5436 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5437 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, 1, 1, -10, 100, NULL);
5438 R_Mesh_ResetRenderTargets();
5439 R_SetViewport(&viewport);
5440 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5441 GL_Color(1, 1, 1, 1);
5442 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5443 GL_BlendFunc(GL_ONE, GL_ZERO);
5444 GL_ScissorTest(false);
5445 GL_DepthMask(false);
5446 GL_DepthRange(0, 1);
5447 GL_DepthTest(false);
5448 GL_DepthFunc(GL_LEQUAL);
5449 R_EntityMatrix(&identitymatrix);
5450 R_Mesh_ResetTextureState();
5451 GL_PolygonOffset(0, 0);
5452 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5453 switch(vid.renderpath)
5455 case RENDERPATH_GL11:
5456 case RENDERPATH_GL13:
5457 case RENDERPATH_GL20:
5458 case RENDERPATH_GLES1:
5459 case RENDERPATH_GLES2:
5460 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5462 case RENDERPATH_D3D9:
5463 case RENDERPATH_D3D10:
5464 case RENDERPATH_D3D11:
5465 case RENDERPATH_SOFT:
5468 GL_CullFace(GL_NONE);
5471 void R_ResetViewRendering3D(void)
5476 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5477 GL_Color(1, 1, 1, 1);
5478 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5479 GL_BlendFunc(GL_ONE, GL_ZERO);
5480 GL_ScissorTest(true);
5482 GL_DepthRange(0, 1);
5484 GL_DepthFunc(GL_LEQUAL);
5485 R_EntityMatrix(&identitymatrix);
5486 R_Mesh_ResetTextureState();
5487 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5488 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5489 switch(vid.renderpath)
5491 case RENDERPATH_GL11:
5492 case RENDERPATH_GL13:
5493 case RENDERPATH_GL20:
5494 case RENDERPATH_GLES1:
5495 case RENDERPATH_GLES2:
5496 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5498 case RENDERPATH_D3D9:
5499 case RENDERPATH_D3D10:
5500 case RENDERPATH_D3D11:
5501 case RENDERPATH_SOFT:
5504 GL_CullFace(r_refdef.view.cullface_back);
5509 R_RenderView_UpdateViewVectors
5512 static void R_RenderView_UpdateViewVectors(void)
5514 // break apart the view matrix into vectors for various purposes
5515 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5516 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5517 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5518 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5519 // make an inverted copy of the view matrix for tracking sprites
5520 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5523 void R_RenderScene(void);
5524 void R_RenderWaterPlanes(void);
5526 static void R_Water_StartFrame(void)
5529 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5530 r_waterstate_waterplane_t *p;
5532 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5535 switch(vid.renderpath)
5537 case RENDERPATH_GL20:
5538 case RENDERPATH_D3D9:
5539 case RENDERPATH_D3D10:
5540 case RENDERPATH_D3D11:
5541 case RENDERPATH_SOFT:
5542 case RENDERPATH_GLES2:
5544 case RENDERPATH_GL11:
5545 case RENDERPATH_GL13:
5546 case RENDERPATH_GLES1:
5550 // set waterwidth and waterheight to the water resolution that will be
5551 // used (often less than the screen resolution for faster rendering)
5552 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5554 // calculate desired texture sizes
5555 // can't use water if the card does not support the texture size
5556 if (!r_water.integer || r_showsurfaces.integer)
5557 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5558 else if (vid.support.arb_texture_non_power_of_two)
5560 texturewidth = waterwidth;
5561 textureheight = waterheight;
5562 camerawidth = waterwidth;
5563 cameraheight = waterheight;
5567 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5568 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5569 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5570 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5573 // allocate textures as needed
5574 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5576 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5577 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5579 if (p->texture_refraction)
5580 R_FreeTexture(p->texture_refraction);
5581 p->texture_refraction = NULL;
5582 if (p->texture_reflection)
5583 R_FreeTexture(p->texture_reflection);
5584 p->texture_reflection = NULL;
5585 if (p->texture_camera)
5586 R_FreeTexture(p->texture_camera);
5587 p->texture_camera = NULL;
5589 memset(&r_waterstate, 0, sizeof(r_waterstate));
5590 r_waterstate.texturewidth = texturewidth;
5591 r_waterstate.textureheight = textureheight;
5592 r_waterstate.camerawidth = camerawidth;
5593 r_waterstate.cameraheight = cameraheight;
5596 if (r_waterstate.texturewidth)
5598 int scaledwidth, scaledheight;
5600 r_waterstate.enabled = true;
5602 // when doing a reduced render (HDR) we want to use a smaller area
5603 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5604 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5605 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5607 // set up variables that will be used in shader setup
5608 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5609 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5610 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5611 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5614 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5615 r_waterstate.numwaterplanes = 0;
5618 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5620 int triangleindex, planeindex;
5626 r_waterstate_waterplane_t *p;
5627 texture_t *t = R_GetCurrentTexture(surface->texture);
5629 // just use the first triangle with a valid normal for any decisions
5630 VectorClear(normal);
5631 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5633 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5634 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5635 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5636 TriangleNormal(vert[0], vert[1], vert[2], normal);
5637 if (VectorLength2(normal) >= 0.001)
5641 VectorCopy(normal, plane.normal);
5642 VectorNormalize(plane.normal);
5643 plane.dist = DotProduct(vert[0], plane.normal);
5644 PlaneClassify(&plane);
5645 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5647 // skip backfaces (except if nocullface is set)
5648 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5650 VectorNegate(plane.normal, plane.normal);
5652 PlaneClassify(&plane);
5656 // find a matching plane if there is one
5657 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5658 if(p->camera_entity == t->camera_entity)
5659 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5661 if (planeindex >= r_waterstate.maxwaterplanes)
5662 return; // nothing we can do, out of planes
5664 // if this triangle does not fit any known plane rendered this frame, add one
5665 if (planeindex >= r_waterstate.numwaterplanes)
5667 // store the new plane
5668 r_waterstate.numwaterplanes++;
5670 // clear materialflags and pvs
5671 p->materialflags = 0;
5672 p->pvsvalid = false;
5673 p->camera_entity = t->camera_entity;
5674 VectorCopy(surface->mins, p->mins);
5675 VectorCopy(surface->maxs, p->maxs);
5680 p->mins[0] = min(p->mins[0], surface->mins[0]);
5681 p->mins[1] = min(p->mins[1], surface->mins[1]);
5682 p->mins[2] = min(p->mins[2], surface->mins[2]);
5683 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5684 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5685 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5687 // merge this surface's materialflags into the waterplane
5688 p->materialflags |= t->currentmaterialflags;
5689 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5691 // merge this surface's PVS into the waterplane
5692 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5693 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5694 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5696 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5702 extern cvar_t r_drawparticles;
5703 extern cvar_t r_drawdecals;
5705 static void R_Water_ProcessPlanes(void)
5708 r_refdef_view_t originalview;
5709 r_refdef_view_t myview;
5710 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;
5711 r_waterstate_waterplane_t *p;
5714 originalview = r_refdef.view;
5716 // lowquality hack, temporarily shut down some cvars and restore afterwards
5717 qualityreduction = r_water_lowquality.integer;
5718 if (qualityreduction > 0)
5720 if (qualityreduction >= 1)
5722 old_r_shadows = r_shadows.integer;
5723 old_r_worldrtlight = r_shadow_realtime_world.integer;
5724 old_r_dlight = r_shadow_realtime_dlight.integer;
5725 Cvar_SetValueQuick(&r_shadows, 0);
5726 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5727 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5729 if (qualityreduction >= 2)
5731 old_r_dynamic = r_dynamic.integer;
5732 old_r_particles = r_drawparticles.integer;
5733 old_r_decals = r_drawdecals.integer;
5734 Cvar_SetValueQuick(&r_dynamic, 0);
5735 Cvar_SetValueQuick(&r_drawparticles, 0);
5736 Cvar_SetValueQuick(&r_drawdecals, 0);
5740 // make sure enough textures are allocated
5741 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5743 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5745 if (!p->texture_refraction)
5746 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5747 if (!p->texture_refraction)
5750 else if (p->materialflags & MATERIALFLAG_CAMERA)
5752 if (!p->texture_camera)
5753 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5754 if (!p->texture_camera)
5758 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5760 if (!p->texture_reflection)
5761 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5762 if (!p->texture_reflection)
5768 r_refdef.view = originalview;
5769 r_refdef.view.showdebug = false;
5770 r_refdef.view.width = r_waterstate.waterwidth;
5771 r_refdef.view.height = r_waterstate.waterheight;
5772 r_refdef.view.useclipplane = true;
5773 myview = r_refdef.view;
5774 r_waterstate.renderingscene = true;
5775 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5777 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5779 r_refdef.view = myview;
5780 if(r_water_scissormode.integer)
5783 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5784 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5787 // render reflected scene and copy into texture
5788 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5789 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5790 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5791 r_refdef.view.clipplane = p->plane;
5792 // reverse the cullface settings for this render
5793 r_refdef.view.cullface_front = GL_FRONT;
5794 r_refdef.view.cullface_back = GL_BACK;
5795 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5797 r_refdef.view.usecustompvs = true;
5799 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5801 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5804 R_ResetViewRendering3D();
5805 R_ClearScreen(r_refdef.fogenabled);
5806 if(r_water_scissormode.integer & 2)
5807 R_View_UpdateWithScissor(myscissor);
5810 if(r_water_scissormode.integer & 1)
5811 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5814 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);
5817 // render the normal view scene and copy into texture
5818 // (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)
5819 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5821 r_refdef.view = myview;
5822 if(r_water_scissormode.integer)
5825 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5826 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5829 r_waterstate.renderingrefraction = true;
5831 r_refdef.view.clipplane = p->plane;
5832 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5833 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5835 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5837 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5838 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5839 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5840 R_RenderView_UpdateViewVectors();
5841 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5843 r_refdef.view.usecustompvs = true;
5844 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);
5848 PlaneClassify(&r_refdef.view.clipplane);
5850 R_ResetViewRendering3D();
5851 R_ClearScreen(r_refdef.fogenabled);
5852 if(r_water_scissormode.integer & 2)
5853 R_View_UpdateWithScissor(myscissor);
5856 if(r_water_scissormode.integer & 1)
5857 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5860 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);
5861 r_waterstate.renderingrefraction = false;
5863 else if (p->materialflags & MATERIALFLAG_CAMERA)
5865 r_refdef.view = myview;
5867 r_refdef.view.clipplane = p->plane;
5868 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5869 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5871 r_refdef.view.width = r_waterstate.camerawidth;
5872 r_refdef.view.height = r_waterstate.cameraheight;
5873 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5874 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5876 if(p->camera_entity)
5878 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5879 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5882 // note: all of the view is used for displaying... so
5883 // there is no use in scissoring
5885 // reverse the cullface settings for this render
5886 r_refdef.view.cullface_front = GL_FRONT;
5887 r_refdef.view.cullface_back = GL_BACK;
5888 // also reverse the view matrix
5889 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
5890 R_RenderView_UpdateViewVectors();
5891 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5893 r_refdef.view.usecustompvs = true;
5894 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);
5897 // camera needs no clipplane
5898 r_refdef.view.useclipplane = false;
5900 PlaneClassify(&r_refdef.view.clipplane);
5902 R_ResetViewRendering3D();
5903 R_ClearScreen(r_refdef.fogenabled);
5907 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);
5908 r_waterstate.renderingrefraction = false;
5912 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5913 r_waterstate.renderingscene = false;
5914 r_refdef.view = originalview;
5915 R_ResetViewRendering3D();
5916 R_ClearScreen(r_refdef.fogenabled);
5920 r_refdef.view = originalview;
5921 r_waterstate.renderingscene = false;
5922 Cvar_SetValueQuick(&r_water, 0);
5923 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5925 // lowquality hack, restore cvars
5926 if (qualityreduction > 0)
5928 if (qualityreduction >= 1)
5930 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5931 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5932 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5934 if (qualityreduction >= 2)
5936 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5937 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5938 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5943 void R_Bloom_StartFrame(void)
5945 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5946 int viewwidth, viewheight;
5949 if (r_viewscale_fpsscaling.integer)
5951 double actualframetime;
5952 double targetframetime;
5954 actualframetime = r_refdef.lastdrawscreentime;
5955 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5956 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5957 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5958 if (r_viewscale_fpsscaling_stepsize.value > 0)
5959 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5960 viewscalefpsadjusted += adjust;
5961 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5964 viewscalefpsadjusted = 1.0f;
5966 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5968 switch(vid.renderpath)
5970 case RENDERPATH_GL20:
5971 case RENDERPATH_D3D9:
5972 case RENDERPATH_D3D10:
5973 case RENDERPATH_D3D11:
5974 case RENDERPATH_SOFT:
5975 case RENDERPATH_GLES2:
5977 case RENDERPATH_GL11:
5978 case RENDERPATH_GL13:
5979 case RENDERPATH_GLES1:
5983 // set bloomwidth and bloomheight to the bloom resolution that will be
5984 // used (often less than the screen resolution for faster rendering)
5985 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5986 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5987 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5988 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5989 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5991 // calculate desired texture sizes
5992 if (vid.support.arb_texture_non_power_of_two)
5994 screentexturewidth = vid.width;
5995 screentextureheight = vid.height;
5996 bloomtexturewidth = r_bloomstate.bloomwidth;
5997 bloomtextureheight = r_bloomstate.bloomheight;
6001 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6002 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6003 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
6004 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
6007 if ((r_hdr.integer || 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))
6009 Cvar_SetValueQuick(&r_hdr, 0);
6010 Cvar_SetValueQuick(&r_bloom, 0);
6011 Cvar_SetValueQuick(&r_motionblur, 0);
6012 Cvar_SetValueQuick(&r_damageblur, 0);
6015 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
6016 screentexturewidth = screentextureheight = 0;
6017 if (!r_hdr.integer && !r_bloom.integer)
6018 bloomtexturewidth = bloomtextureheight = 0;
6020 textype = TEXTYPE_COLORBUFFER;
6021 switch (vid.renderpath)
6023 case RENDERPATH_GL20:
6024 case RENDERPATH_GLES2:
6025 if (vid.support.ext_framebuffer_object)
6027 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6028 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6031 case RENDERPATH_GL11:
6032 case RENDERPATH_GL13:
6033 case RENDERPATH_GLES1:
6034 case RENDERPATH_D3D9:
6035 case RENDERPATH_D3D10:
6036 case RENDERPATH_D3D11:
6037 case RENDERPATH_SOFT:
6041 // allocate textures as needed
6042 if (r_bloomstate.screentexturewidth != screentexturewidth
6043 || r_bloomstate.screentextureheight != screentextureheight
6044 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6045 || r_bloomstate.bloomtextureheight != bloomtextureheight
6046 || r_bloomstate.texturetype != textype
6047 || r_bloomstate.viewfbo != r_viewfbo.integer)
6049 if (r_bloomstate.texture_bloom)
6050 R_FreeTexture(r_bloomstate.texture_bloom);
6051 r_bloomstate.texture_bloom = NULL;
6052 if (r_bloomstate.texture_screen)
6053 R_FreeTexture(r_bloomstate.texture_screen);
6054 r_bloomstate.texture_screen = NULL;
6055 if (r_bloomstate.fbo_framebuffer)
6056 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6057 r_bloomstate.fbo_framebuffer = 0;
6058 if (r_bloomstate.texture_framebuffercolor)
6059 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6060 r_bloomstate.texture_framebuffercolor = NULL;
6061 if (r_bloomstate.texture_framebufferdepth)
6062 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6063 r_bloomstate.texture_framebufferdepth = NULL;
6064 r_bloomstate.screentexturewidth = screentexturewidth;
6065 r_bloomstate.screentextureheight = screentextureheight;
6066 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6067 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6068 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6070 // FIXME: choose depth bits based on a cvar
6071 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6072 r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6073 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6074 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6076 // render depth into one texture and normalmap into the other
6080 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6081 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6082 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6083 if (status != GL_FRAMEBUFFER_COMPLETE)
6084 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6088 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6089 r_bloomstate.bloomtextureheight = bloomtextureheight;
6090 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6091 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6092 r_bloomstate.viewfbo = r_viewfbo.integer;
6093 r_bloomstate.texturetype = textype;
6096 // when doing a reduced render (HDR) we want to use a smaller area
6097 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6098 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6099 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6100 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6101 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6103 // set up a texcoord array for the full resolution screen image
6104 // (we have to keep this around to copy back during final render)
6105 r_bloomstate.screentexcoord2f[0] = 0;
6106 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6107 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6108 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6109 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6110 r_bloomstate.screentexcoord2f[5] = 0;
6111 r_bloomstate.screentexcoord2f[6] = 0;
6112 r_bloomstate.screentexcoord2f[7] = 0;
6114 // set up a texcoord array for the reduced resolution bloom image
6115 // (which will be additive blended over the screen image)
6116 r_bloomstate.bloomtexcoord2f[0] = 0;
6117 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6118 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6119 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6120 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6121 r_bloomstate.bloomtexcoord2f[5] = 0;
6122 r_bloomstate.bloomtexcoord2f[6] = 0;
6123 r_bloomstate.bloomtexcoord2f[7] = 0;
6125 switch(vid.renderpath)
6127 case RENDERPATH_GL11:
6128 case RENDERPATH_GL13:
6129 case RENDERPATH_GL20:
6130 case RENDERPATH_SOFT:
6131 case RENDERPATH_GLES1:
6132 case RENDERPATH_GLES2:
6134 case RENDERPATH_D3D9:
6135 case RENDERPATH_D3D10:
6136 case RENDERPATH_D3D11:
6139 for (i = 0;i < 4;i++)
6141 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6142 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6143 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6144 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6150 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6152 r_bloomstate.enabled = true;
6153 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6156 R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6158 if (r_bloomstate.fbo_framebuffer)
6159 r_refdef.view.clear = true;
6162 void R_Bloom_CopyBloomTexture(float colorscale)
6164 r_refdef.stats.bloom++;
6166 // scale down screen texture to the bloom texture size
6168 R_Mesh_SetMainRenderTargets();
6169 R_SetViewport(&r_bloomstate.viewport);
6170 GL_BlendFunc(GL_ONE, GL_ZERO);
6171 GL_Color(colorscale, colorscale, colorscale, 1);
6172 // 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...
6173 switch(vid.renderpath)
6175 case RENDERPATH_GL11:
6176 case RENDERPATH_GL13:
6177 case RENDERPATH_GL20:
6178 case RENDERPATH_GLES1:
6179 case RENDERPATH_GLES2:
6180 case RENDERPATH_SOFT:
6181 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6183 case RENDERPATH_D3D9:
6184 case RENDERPATH_D3D10:
6185 case RENDERPATH_D3D11:
6186 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6189 // TODO: do boxfilter scale-down in shader?
6190 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6191 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6192 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6194 // we now have a bloom image in the framebuffer
6195 // copy it into the bloom image texture for later processing
6196 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6197 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6200 void R_Bloom_CopyHDRTexture(void)
6202 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6203 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6206 void R_Bloom_MakeTexture(void)
6209 float xoffset, yoffset, r, brighten;
6211 r_refdef.stats.bloom++;
6213 R_ResetViewRendering2D();
6215 // we have a bloom image in the framebuffer
6217 R_SetViewport(&r_bloomstate.viewport);
6219 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6222 r = bound(0, r_bloom_colorexponent.value / x, 1);
6223 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6225 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6226 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6227 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6228 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6230 // copy the vertically blurred bloom view to a texture
6231 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6232 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6235 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6236 brighten = r_bloom_brighten.value;
6237 if (r_bloomstate.hdr)
6238 brighten *= r_hdr_range.value;
6239 brighten = sqrt(brighten);
6241 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6242 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6244 for (dir = 0;dir < 2;dir++)
6246 // blend on at multiple vertical offsets to achieve a vertical blur
6247 // TODO: do offset blends using GLSL
6248 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6249 GL_BlendFunc(GL_ONE, GL_ZERO);
6250 for (x = -range;x <= range;x++)
6252 if (!dir){xoffset = 0;yoffset = x;}
6253 else {xoffset = x;yoffset = 0;}
6254 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6255 yoffset /= (float)r_bloomstate.bloomtextureheight;
6256 // compute a texcoord array with the specified x and y offset
6257 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6258 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6259 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6260 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6261 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6262 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6263 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6264 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6265 // this r value looks like a 'dot' particle, fading sharply to
6266 // black at the edges
6267 // (probably not realistic but looks good enough)
6268 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6269 //r = brighten/(range*2+1);
6270 r = brighten / (range * 2 + 1);
6272 r *= (1 - x*x/(float)(range*range));
6273 GL_Color(r, r, r, 1);
6274 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6275 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6276 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6277 GL_BlendFunc(GL_ONE, GL_ONE);
6280 // copy the vertically blurred bloom view to a texture
6281 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6282 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6286 void R_HDR_RenderBloomTexture(void)
6288 int oldwidth, oldheight;
6289 float oldcolorscale;
6290 qboolean oldwaterstate;
6292 oldwaterstate = r_waterstate.enabled;
6293 oldcolorscale = r_refdef.view.colorscale;
6294 oldwidth = r_refdef.view.width;
6295 oldheight = r_refdef.view.height;
6296 r_refdef.view.width = r_bloomstate.bloomwidth;
6297 r_refdef.view.height = r_bloomstate.bloomheight;
6299 if(r_hdr.integer < 2)
6300 r_waterstate.enabled = false;
6302 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6303 // TODO: add exposure compensation features
6304 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6306 r_refdef.view.showdebug = false;
6307 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6309 R_ResetViewRendering3D();
6311 R_ClearScreen(r_refdef.fogenabled);
6312 if (r_timereport_active)
6313 R_TimeReport("HDRclear");
6316 if (r_timereport_active)
6317 R_TimeReport("visibility");
6319 // only do secondary renders with HDR if r_hdr is 2 or higher
6320 r_waterstate.numwaterplanes = 0;
6321 if (r_waterstate.enabled)
6322 R_RenderWaterPlanes();
6324 r_refdef.view.showdebug = true;
6326 r_waterstate.numwaterplanes = 0;
6328 R_ResetViewRendering2D();
6330 R_Bloom_CopyHDRTexture();
6331 R_Bloom_MakeTexture();
6333 // restore the view settings
6334 r_waterstate.enabled = oldwaterstate;
6335 r_refdef.view.width = oldwidth;
6336 r_refdef.view.height = oldheight;
6337 r_refdef.view.colorscale = oldcolorscale;
6339 R_ResetViewRendering3D();
6341 R_ClearScreen(r_refdef.fogenabled);
6342 if (r_timereport_active)
6343 R_TimeReport("viewclear");
6346 static void R_BlendView(void)
6348 unsigned int permutation;
6349 float uservecs[4][4];
6351 switch (vid.renderpath)
6353 case RENDERPATH_GL20:
6354 case RENDERPATH_D3D9:
6355 case RENDERPATH_D3D10:
6356 case RENDERPATH_D3D11:
6357 case RENDERPATH_SOFT:
6358 case RENDERPATH_GLES2:
6360 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6361 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6362 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6363 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6364 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6366 if (r_bloomstate.texture_screen)
6368 // make sure the buffer is available
6369 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6371 R_ResetViewRendering2D();
6372 R_Mesh_SetMainRenderTargets();
6374 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6376 // declare variables
6377 float blur_factor, blur_mouseaccel, blur_velocity;
6378 static float blur_average;
6379 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6381 // set a goal for the factoring
6382 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6383 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6384 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6385 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6386 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6387 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6389 // from the goal, pick an averaged value between goal and last value
6390 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6391 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6393 // enforce minimum amount of blur
6394 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6396 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6398 // calculate values into a standard alpha
6399 cl.motionbluralpha = 1 - exp(-
6401 (r_motionblur.value * blur_factor / 80)
6403 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6406 max(0.0001, cl.time - cl.oldtime) // fps independent
6409 // randomization for the blur value to combat persistent ghosting
6410 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6411 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6414 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6416 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6417 GL_Color(1, 1, 1, cl.motionbluralpha);
6418 switch(vid.renderpath)
6420 case RENDERPATH_GL11:
6421 case RENDERPATH_GL13:
6422 case RENDERPATH_GL20:
6423 case RENDERPATH_GLES1:
6424 case RENDERPATH_GLES2:
6425 case RENDERPATH_SOFT:
6426 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6428 case RENDERPATH_D3D9:
6429 case RENDERPATH_D3D10:
6430 case RENDERPATH_D3D11:
6431 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6434 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6435 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6436 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6439 // updates old view angles for next pass
6440 VectorCopy(cl.viewangles, blur_oldangles);
6443 // copy view into the screen texture
6444 R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6445 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6447 else if (!r_bloomstate.texture_bloom)
6449 // we may still have to do view tint...
6450 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6452 // apply a color tint to the whole view
6453 R_ResetViewRendering2D();
6454 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6455 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6456 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6457 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6458 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6460 break; // no screen processing, no bloom, skip it
6463 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6465 // render simple bloom effect
6466 // copy the screen and shrink it and darken it for the bloom process
6467 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6468 // make the bloom texture
6469 R_Bloom_MakeTexture();
6472 #if _MSC_VER >= 1400
6473 #define sscanf sscanf_s
6475 memset(uservecs, 0, sizeof(uservecs));
6476 if (r_glsl_postprocess_uservec1_enable.integer)
6477 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6478 if (r_glsl_postprocess_uservec2_enable.integer)
6479 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6480 if (r_glsl_postprocess_uservec3_enable.integer)
6481 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6482 if (r_glsl_postprocess_uservec4_enable.integer)
6483 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6485 R_ResetViewRendering2D();
6486 GL_Color(1, 1, 1, 1);
6487 GL_BlendFunc(GL_ONE, GL_ZERO);
6489 switch(vid.renderpath)
6491 case RENDERPATH_GL20:
6492 case RENDERPATH_GLES2:
6493 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6494 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6495 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6496 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6497 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6498 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]);
6499 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6500 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]);
6501 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]);
6502 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]);
6503 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]);
6504 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6505 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6506 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);
6508 case RENDERPATH_D3D9:
6510 // 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...
6511 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6512 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6513 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6514 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6515 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6516 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6517 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6518 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6519 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6520 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6521 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6522 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6523 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6524 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6527 case RENDERPATH_D3D10:
6528 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6530 case RENDERPATH_D3D11:
6531 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6533 case RENDERPATH_SOFT:
6534 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6535 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6536 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6537 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6538 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6539 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6540 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6541 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6542 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6543 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6544 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6545 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6546 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6547 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6552 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6553 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6555 case RENDERPATH_GL11:
6556 case RENDERPATH_GL13:
6557 case RENDERPATH_GLES1:
6558 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6560 // apply a color tint to the whole view
6561 R_ResetViewRendering2D();
6562 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6563 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6564 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6565 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6566 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6572 matrix4x4_t r_waterscrollmatrix;
6574 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6576 if (r_refdef.fog_density)
6578 r_refdef.fogcolor[0] = r_refdef.fog_red;
6579 r_refdef.fogcolor[1] = r_refdef.fog_green;
6580 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6582 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6583 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6584 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6585 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6589 VectorCopy(r_refdef.fogcolor, fogvec);
6590 // color.rgb *= ContrastBoost * SceneBrightness;
6591 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6592 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6593 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6594 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6599 void R_UpdateVariables(void)
6603 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6605 r_refdef.farclip = r_farclip_base.value;
6606 if (r_refdef.scene.worldmodel)
6607 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6608 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6610 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6611 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6612 r_refdef.polygonfactor = 0;
6613 r_refdef.polygonoffset = 0;
6614 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6615 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6617 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6618 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6619 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6620 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6621 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6622 if (FAKELIGHT_ENABLED)
6624 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6626 if (r_showsurfaces.integer)
6628 r_refdef.scene.rtworld = false;
6629 r_refdef.scene.rtworldshadows = false;
6630 r_refdef.scene.rtdlight = false;
6631 r_refdef.scene.rtdlightshadows = false;
6632 r_refdef.lightmapintensity = 0;
6635 if (gamemode == GAME_NEHAHRA)
6637 if (gl_fogenable.integer)
6639 r_refdef.oldgl_fogenable = true;
6640 r_refdef.fog_density = gl_fogdensity.value;
6641 r_refdef.fog_red = gl_fogred.value;
6642 r_refdef.fog_green = gl_foggreen.value;
6643 r_refdef.fog_blue = gl_fogblue.value;
6644 r_refdef.fog_alpha = 1;
6645 r_refdef.fog_start = 0;
6646 r_refdef.fog_end = gl_skyclip.value;
6647 r_refdef.fog_height = 1<<30;
6648 r_refdef.fog_fadedepth = 128;
6650 else if (r_refdef.oldgl_fogenable)
6652 r_refdef.oldgl_fogenable = false;
6653 r_refdef.fog_density = 0;
6654 r_refdef.fog_red = 0;
6655 r_refdef.fog_green = 0;
6656 r_refdef.fog_blue = 0;
6657 r_refdef.fog_alpha = 0;
6658 r_refdef.fog_start = 0;
6659 r_refdef.fog_end = 0;
6660 r_refdef.fog_height = 1<<30;
6661 r_refdef.fog_fadedepth = 128;
6665 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6666 r_refdef.fog_start = max(0, r_refdef.fog_start);
6667 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6669 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6671 if (r_refdef.fog_density && r_drawfog.integer)
6673 r_refdef.fogenabled = true;
6674 // this is the point where the fog reaches 0.9986 alpha, which we
6675 // consider a good enough cutoff point for the texture
6676 // (0.9986 * 256 == 255.6)
6677 if (r_fog_exp2.integer)
6678 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6680 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6681 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6682 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6683 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6684 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6685 R_BuildFogHeightTexture();
6686 // fog color was already set
6687 // update the fog texture
6688 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)
6689 R_BuildFogTexture();
6690 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6691 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6694 r_refdef.fogenabled = false;
6696 switch(vid.renderpath)
6698 case RENDERPATH_GL20:
6699 case RENDERPATH_D3D9:
6700 case RENDERPATH_D3D10:
6701 case RENDERPATH_D3D11:
6702 case RENDERPATH_SOFT:
6703 case RENDERPATH_GLES2:
6704 if(v_glslgamma.integer && !vid_gammatables_trivial)
6706 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6708 // build GLSL gamma texture
6709 #define RAMPWIDTH 256
6710 unsigned short ramp[RAMPWIDTH * 3];
6711 unsigned char rampbgr[RAMPWIDTH][4];
6714 r_texture_gammaramps_serial = vid_gammatables_serial;
6716 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6717 for(i = 0; i < RAMPWIDTH; ++i)
6719 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6720 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6721 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6724 if (r_texture_gammaramps)
6726 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6730 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6736 // remove GLSL gamma texture
6739 case RENDERPATH_GL11:
6740 case RENDERPATH_GL13:
6741 case RENDERPATH_GLES1:
6746 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6747 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6753 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6754 if( scenetype != r_currentscenetype ) {
6755 // store the old scenetype
6756 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6757 r_currentscenetype = scenetype;
6758 // move in the new scene
6759 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6768 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6770 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6771 if( scenetype == r_currentscenetype ) {
6772 return &r_refdef.scene;
6774 return &r_scenes_store[ scenetype ];
6778 int R_SortEntities_Compare(const void *ap, const void *bp)
6780 const entity_render_t *a = *(const entity_render_t **)ap;
6781 const entity_render_t *b = *(const entity_render_t **)bp;
6784 if(a->model < b->model)
6786 if(a->model > b->model)
6790 // TODO possibly calculate the REAL skinnum here first using
6792 if(a->skinnum < b->skinnum)
6794 if(a->skinnum > b->skinnum)
6797 // everything we compared is equal
6800 void R_SortEntities(void)
6802 // below or equal 2 ents, sorting never gains anything
6803 if(r_refdef.scene.numentities <= 2)
6806 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6814 int dpsoftrast_test;
6815 extern void R_Shadow_UpdateBounceGridTexture(void);
6816 extern cvar_t r_shadow_bouncegrid;
6817 void R_RenderView(void)
6819 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6821 dpsoftrast_test = r_test.integer;
6823 if (r_timereport_active)
6824 R_TimeReport("start");
6825 r_textureframe++; // used only by R_GetCurrentTexture
6826 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6828 if(R_CompileShader_CheckStaticParms())
6831 if (!r_drawentities.integer)
6832 r_refdef.scene.numentities = 0;
6833 else if (r_sortentities.integer)
6836 R_AnimCache_ClearCache();
6837 R_FrameData_NewFrame();
6839 /* adjust for stereo display */
6840 if(R_Stereo_Active())
6842 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);
6843 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6846 if (r_refdef.view.isoverlay)
6848 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6849 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6850 R_TimeReport("depthclear");
6852 r_refdef.view.showdebug = false;
6854 r_waterstate.enabled = false;
6855 r_waterstate.numwaterplanes = 0;
6859 r_refdef.view.matrix = originalmatrix;
6865 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6867 r_refdef.view.matrix = originalmatrix;
6868 return; //Host_Error ("R_RenderView: NULL worldmodel");
6871 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6873 R_RenderView_UpdateViewVectors();
6875 R_Shadow_UpdateWorldLightSelection();
6877 R_Bloom_StartFrame();
6878 R_Water_StartFrame();
6881 if (r_timereport_active)
6882 R_TimeReport("viewsetup");
6884 R_ResetViewRendering3D();
6886 if (r_refdef.view.clear || r_refdef.fogenabled)
6888 R_ClearScreen(r_refdef.fogenabled);
6889 if (r_timereport_active)
6890 R_TimeReport("viewclear");
6892 r_refdef.view.clear = true;
6894 // this produces a bloom texture to be used in R_BlendView() later
6895 if (r_bloomstate.hdr)
6897 R_HDR_RenderBloomTexture();
6898 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6899 r_textureframe++; // used only by R_GetCurrentTexture
6902 r_refdef.view.showdebug = true;
6905 if (r_timereport_active)
6906 R_TimeReport("visibility");
6908 R_Shadow_UpdateBounceGridTexture();
6909 if (r_timereport_active && r_shadow_bouncegrid.integer)
6910 R_TimeReport("bouncegrid");
6912 r_waterstate.numwaterplanes = 0;
6913 if (r_waterstate.enabled)
6914 R_RenderWaterPlanes();
6917 r_waterstate.numwaterplanes = 0;
6920 if (r_timereport_active)
6921 R_TimeReport("blendview");
6923 GL_Scissor(0, 0, vid.width, vid.height);
6924 GL_ScissorTest(false);
6926 r_refdef.view.matrix = originalmatrix;
6931 void R_RenderWaterPlanes(void)
6933 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6935 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6936 if (r_timereport_active)
6937 R_TimeReport("waterworld");
6940 // don't let sound skip if going slow
6941 if (r_refdef.scene.extraupdate)
6944 R_DrawModelsAddWaterPlanes();
6945 if (r_timereport_active)
6946 R_TimeReport("watermodels");
6948 if (r_waterstate.numwaterplanes)
6950 R_Water_ProcessPlanes();
6951 if (r_timereport_active)
6952 R_TimeReport("waterscenes");
6956 extern void R_DrawLightningBeams (void);
6957 extern void VM_CL_AddPolygonsToMeshQueue (void);
6958 extern void R_DrawPortals (void);
6959 extern cvar_t cl_locs_show;
6960 static void R_DrawLocs(void);
6961 static void R_DrawEntityBBoxes(void);
6962 static void R_DrawModelDecals(void);
6963 extern void R_DrawModelShadows(void);
6964 extern void R_DrawModelShadowMaps(void);
6965 extern cvar_t cl_decals_newsystem;
6966 extern qboolean r_shadow_usingdeferredprepass;
6967 void R_RenderScene(void)
6969 qboolean shadowmapping = false;
6971 if (r_timereport_active)
6972 R_TimeReport("beginscene");
6974 r_refdef.stats.renders++;
6978 // don't let sound skip if going slow
6979 if (r_refdef.scene.extraupdate)
6982 R_MeshQueue_BeginScene();
6986 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);
6988 if (r_timereport_active)
6989 R_TimeReport("skystartframe");
6991 if (cl.csqc_vidvars.drawworld)
6993 // don't let sound skip if going slow
6994 if (r_refdef.scene.extraupdate)
6997 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6999 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7000 if (r_timereport_active)
7001 R_TimeReport("worldsky");
7004 if (R_DrawBrushModelsSky() && r_timereport_active)
7005 R_TimeReport("bmodelsky");
7007 if (skyrendermasked && skyrenderlater)
7009 // we have to force off the water clipping plane while rendering sky
7013 if (r_timereport_active)
7014 R_TimeReport("sky");
7018 R_AnimCache_CacheVisibleEntities();
7019 if (r_timereport_active)
7020 R_TimeReport("animation");
7022 R_Shadow_PrepareLights();
7023 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7024 R_Shadow_PrepareModelShadows();
7025 if (r_timereport_active)
7026 R_TimeReport("preparelights");
7028 if (R_Shadow_ShadowMappingEnabled())
7029 shadowmapping = true;
7031 if (r_shadow_usingdeferredprepass)
7032 R_Shadow_DrawPrepass();
7034 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7036 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7037 if (r_timereport_active)
7038 R_TimeReport("worlddepth");
7040 if (r_depthfirst.integer >= 2)
7042 R_DrawModelsDepth();
7043 if (r_timereport_active)
7044 R_TimeReport("modeldepth");
7047 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7049 R_DrawModelShadowMaps();
7050 R_ResetViewRendering3D();
7051 // don't let sound skip if going slow
7052 if (r_refdef.scene.extraupdate)
7056 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7058 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7059 if (r_timereport_active)
7060 R_TimeReport("world");
7063 // don't let sound skip if going slow
7064 if (r_refdef.scene.extraupdate)
7068 if (r_timereport_active)
7069 R_TimeReport("models");
7071 // don't let sound skip if going slow
7072 if (r_refdef.scene.extraupdate)
7075 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7077 R_DrawModelShadows();
7078 R_ResetViewRendering3D();
7079 // don't let sound skip if going slow
7080 if (r_refdef.scene.extraupdate)
7084 if (!r_shadow_usingdeferredprepass)
7086 R_Shadow_DrawLights();
7087 if (r_timereport_active)
7088 R_TimeReport("rtlights");
7091 // don't let sound skip if going slow
7092 if (r_refdef.scene.extraupdate)
7095 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7097 R_DrawModelShadows();
7098 R_ResetViewRendering3D();
7099 // don't let sound skip if going slow
7100 if (r_refdef.scene.extraupdate)
7104 if (cl.csqc_vidvars.drawworld)
7106 if (cl_decals_newsystem.integer)
7108 R_DrawModelDecals();
7109 if (r_timereport_active)
7110 R_TimeReport("modeldecals");
7115 if (r_timereport_active)
7116 R_TimeReport("decals");
7120 if (r_timereport_active)
7121 R_TimeReport("particles");
7124 if (r_timereport_active)
7125 R_TimeReport("explosions");
7127 R_DrawLightningBeams();
7128 if (r_timereport_active)
7129 R_TimeReport("lightning");
7132 VM_CL_AddPolygonsToMeshQueue();
7134 if (r_refdef.view.showdebug)
7136 if (cl_locs_show.integer)
7139 if (r_timereport_active)
7140 R_TimeReport("showlocs");
7143 if (r_drawportals.integer)
7146 if (r_timereport_active)
7147 R_TimeReport("portals");
7150 if (r_showbboxes.value > 0)
7152 R_DrawEntityBBoxes();
7153 if (r_timereport_active)
7154 R_TimeReport("bboxes");
7158 if (r_transparent.integer)
7160 R_MeshQueue_RenderTransparent();
7161 if (r_timereport_active)
7162 R_TimeReport("drawtrans");
7165 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))
7167 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7168 if (r_timereport_active)
7169 R_TimeReport("worlddebug");
7170 R_DrawModelsDebug();
7171 if (r_timereport_active)
7172 R_TimeReport("modeldebug");
7175 if (cl.csqc_vidvars.drawworld)
7177 R_Shadow_DrawCoronas();
7178 if (r_timereport_active)
7179 R_TimeReport("coronas");
7184 GL_DepthTest(false);
7185 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7186 GL_Color(1, 1, 1, 1);
7187 qglBegin(GL_POLYGON);
7188 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7189 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7190 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7191 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7193 qglBegin(GL_POLYGON);
7194 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]);
7195 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]);
7196 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]);
7197 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]);
7199 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7203 // don't let sound skip if going slow
7204 if (r_refdef.scene.extraupdate)
7207 R_ResetViewRendering2D();
7210 static const unsigned short bboxelements[36] =
7220 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7223 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7225 RSurf_ActiveWorldEntity();
7227 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7228 GL_DepthMask(false);
7229 GL_DepthRange(0, 1);
7230 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7231 // R_Mesh_ResetTextureState();
7233 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7234 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7235 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7236 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7237 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7238 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7239 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7240 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7241 R_FillColors(color4f, 8, cr, cg, cb, ca);
7242 if (r_refdef.fogenabled)
7244 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7246 f1 = RSurf_FogVertex(v);
7248 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7249 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7250 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7253 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7254 R_Mesh_ResetTextureState();
7255 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7256 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7259 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7263 prvm_edict_t *edict;
7264 prvm_prog_t *prog_save = prog;
7266 // this function draws bounding boxes of server entities
7270 GL_CullFace(GL_NONE);
7271 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7275 for (i = 0;i < numsurfaces;i++)
7277 edict = PRVM_EDICT_NUM(surfacelist[i]);
7278 switch ((int)PRVM_serveredictfloat(edict, solid))
7280 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7281 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7282 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7283 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7284 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7285 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7287 color[3] *= r_showbboxes.value;
7288 color[3] = bound(0, color[3], 1);
7289 GL_DepthTest(!r_showdisabledepthtest.integer);
7290 GL_CullFace(r_refdef.view.cullface_front);
7291 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7297 static void R_DrawEntityBBoxes(void)
7300 prvm_edict_t *edict;
7302 prvm_prog_t *prog_save = prog;
7304 // this function draws bounding boxes of server entities
7310 for (i = 0;i < prog->num_edicts;i++)
7312 edict = PRVM_EDICT_NUM(i);
7313 if (edict->priv.server->free)
7315 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7316 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7318 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7320 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7321 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7327 static const int nomodelelement3i[24] =
7339 static const unsigned short nomodelelement3s[24] =
7351 static const float nomodelvertex3f[6*3] =
7361 static const float nomodelcolor4f[6*4] =
7363 0.0f, 0.0f, 0.5f, 1.0f,
7364 0.0f, 0.0f, 0.5f, 1.0f,
7365 0.0f, 0.5f, 0.0f, 1.0f,
7366 0.0f, 0.5f, 0.0f, 1.0f,
7367 0.5f, 0.0f, 0.0f, 1.0f,
7368 0.5f, 0.0f, 0.0f, 1.0f
7371 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7377 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);
7379 // this is only called once per entity so numsurfaces is always 1, and
7380 // surfacelist is always {0}, so this code does not handle batches
7382 if (rsurface.ent_flags & RENDER_ADDITIVE)
7384 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7385 GL_DepthMask(false);
7387 else if (rsurface.colormod[3] < 1)
7389 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7390 GL_DepthMask(false);
7394 GL_BlendFunc(GL_ONE, GL_ZERO);
7397 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7398 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7399 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7400 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7401 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7402 for (i = 0, c = color4f;i < 6;i++, c += 4)
7404 c[0] *= rsurface.colormod[0];
7405 c[1] *= rsurface.colormod[1];
7406 c[2] *= rsurface.colormod[2];
7407 c[3] *= rsurface.colormod[3];
7409 if (r_refdef.fogenabled)
7411 for (i = 0, c = color4f;i < 6;i++, c += 4)
7413 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7415 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7416 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7417 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7420 // R_Mesh_ResetTextureState();
7421 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7422 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7423 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7426 void R_DrawNoModel(entity_render_t *ent)
7429 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7430 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7431 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7433 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7436 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7438 vec3_t right1, right2, diff, normal;
7440 VectorSubtract (org2, org1, normal);
7442 // calculate 'right' vector for start
7443 VectorSubtract (r_refdef.view.origin, org1, diff);
7444 CrossProduct (normal, diff, right1);
7445 VectorNormalize (right1);
7447 // calculate 'right' vector for end
7448 VectorSubtract (r_refdef.view.origin, org2, diff);
7449 CrossProduct (normal, diff, right2);
7450 VectorNormalize (right2);
7452 vert[ 0] = org1[0] + width * right1[0];
7453 vert[ 1] = org1[1] + width * right1[1];
7454 vert[ 2] = org1[2] + width * right1[2];
7455 vert[ 3] = org1[0] - width * right1[0];
7456 vert[ 4] = org1[1] - width * right1[1];
7457 vert[ 5] = org1[2] - width * right1[2];
7458 vert[ 6] = org2[0] - width * right2[0];
7459 vert[ 7] = org2[1] - width * right2[1];
7460 vert[ 8] = org2[2] - width * right2[2];
7461 vert[ 9] = org2[0] + width * right2[0];
7462 vert[10] = org2[1] + width * right2[1];
7463 vert[11] = org2[2] + width * right2[2];
7466 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)
7468 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7469 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7470 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7471 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7472 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7473 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7474 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7475 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7476 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7477 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7478 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7479 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7482 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7487 VectorSet(v, x, y, z);
7488 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7489 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7491 if (i == mesh->numvertices)
7493 if (mesh->numvertices < mesh->maxvertices)
7495 VectorCopy(v, vertex3f);
7496 mesh->numvertices++;
7498 return mesh->numvertices;
7504 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7508 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7509 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7510 e = mesh->element3i + mesh->numtriangles * 3;
7511 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7513 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7514 if (mesh->numtriangles < mesh->maxtriangles)
7519 mesh->numtriangles++;
7521 element[1] = element[2];
7525 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7529 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7530 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7531 e = mesh->element3i + mesh->numtriangles * 3;
7532 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7534 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7535 if (mesh->numtriangles < mesh->maxtriangles)
7540 mesh->numtriangles++;
7542 element[1] = element[2];
7546 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7547 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7549 int planenum, planenum2;
7552 mplane_t *plane, *plane2;
7554 double temppoints[2][256*3];
7555 // figure out how large a bounding box we need to properly compute this brush
7557 for (w = 0;w < numplanes;w++)
7558 maxdist = max(maxdist, fabs(planes[w].dist));
7559 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7560 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7561 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7565 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7566 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7568 if (planenum2 == planenum)
7570 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);
7573 if (tempnumpoints < 3)
7575 // generate elements forming a triangle fan for this polygon
7576 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7580 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)
7582 texturelayer_t *layer;
7583 layer = t->currentlayers + t->currentnumlayers++;
7585 layer->depthmask = depthmask;
7586 layer->blendfunc1 = blendfunc1;
7587 layer->blendfunc2 = blendfunc2;
7588 layer->texture = texture;
7589 layer->texmatrix = *matrix;
7590 layer->color[0] = r;
7591 layer->color[1] = g;
7592 layer->color[2] = b;
7593 layer->color[3] = a;
7596 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7598 if(parms[0] == 0 && parms[1] == 0)
7600 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7601 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7606 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7609 index = parms[2] + rsurface.shadertime * parms[3];
7610 index -= floor(index);
7611 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7614 case Q3WAVEFUNC_NONE:
7615 case Q3WAVEFUNC_NOISE:
7616 case Q3WAVEFUNC_COUNT:
7619 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7620 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7621 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7622 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7623 case Q3WAVEFUNC_TRIANGLE:
7625 f = index - floor(index);
7638 f = parms[0] + parms[1] * f;
7639 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7640 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7644 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7650 matrix4x4_t matrix, temp;
7651 switch(tcmod->tcmod)
7655 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7656 matrix = r_waterscrollmatrix;
7658 matrix = identitymatrix;
7660 case Q3TCMOD_ENTITYTRANSLATE:
7661 // this is used in Q3 to allow the gamecode to control texcoord
7662 // scrolling on the entity, which is not supported in darkplaces yet.
7663 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7665 case Q3TCMOD_ROTATE:
7666 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7667 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7668 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7671 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7673 case Q3TCMOD_SCROLL:
7674 // extra care is needed because of precision breakdown with large values of time
7675 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7676 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7677 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7679 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7680 w = (int) tcmod->parms[0];
7681 h = (int) tcmod->parms[1];
7682 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7684 idx = (int) floor(f * w * h);
7685 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7687 case Q3TCMOD_STRETCH:
7688 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7689 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7691 case Q3TCMOD_TRANSFORM:
7692 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7693 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7694 VectorSet(tcmat + 6, 0 , 0 , 1);
7695 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7696 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7698 case Q3TCMOD_TURBULENT:
7699 // this is handled in the RSurf_PrepareVertices function
7700 matrix = identitymatrix;
7704 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7707 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7709 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7710 char name[MAX_QPATH];
7711 skinframe_t *skinframe;
7712 unsigned char pixels[296*194];
7713 strlcpy(cache->name, skinname, sizeof(cache->name));
7714 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7715 if (developer_loading.integer)
7716 Con_Printf("loading %s\n", name);
7717 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7718 if (!skinframe || !skinframe->base)
7721 fs_offset_t filesize;
7723 f = FS_LoadFile(name, tempmempool, true, &filesize);
7726 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7727 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7731 cache->skinframe = skinframe;
7734 texture_t *R_GetCurrentTexture(texture_t *t)
7737 const entity_render_t *ent = rsurface.entity;
7738 dp_model_t *model = ent->model;
7739 q3shaderinfo_layer_tcmod_t *tcmod;
7741 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7742 return t->currentframe;
7743 t->update_lastrenderframe = r_textureframe;
7744 t->update_lastrenderentity = (void *)ent;
7746 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7747 t->camera_entity = ent->entitynumber;
7749 t->camera_entity = 0;
7751 // switch to an alternate material if this is a q1bsp animated material
7753 texture_t *texture = t;
7754 int s = rsurface.ent_skinnum;
7755 if ((unsigned int)s >= (unsigned int)model->numskins)
7757 if (model->skinscenes)
7759 if (model->skinscenes[s].framecount > 1)
7760 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7762 s = model->skinscenes[s].firstframe;
7765 t = t + s * model->num_surfaces;
7768 // use an alternate animation if the entity's frame is not 0,
7769 // and only if the texture has an alternate animation
7770 if (rsurface.ent_alttextures && t->anim_total[1])
7771 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7773 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7775 texture->currentframe = t;
7778 // update currentskinframe to be a qw skin or animation frame
7779 if (rsurface.ent_qwskin >= 0)
7781 i = rsurface.ent_qwskin;
7782 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7784 r_qwskincache_size = cl.maxclients;
7786 Mem_Free(r_qwskincache);
7787 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7789 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7790 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7791 t->currentskinframe = r_qwskincache[i].skinframe;
7792 if (t->currentskinframe == NULL)
7793 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7795 else if (t->numskinframes >= 2)
7796 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7797 if (t->backgroundnumskinframes >= 2)
7798 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7800 t->currentmaterialflags = t->basematerialflags;
7801 t->currentalpha = rsurface.colormod[3];
7802 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7803 t->currentalpha *= r_wateralpha.value;
7804 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7805 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7806 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7807 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7808 if (!(rsurface.ent_flags & RENDER_LIGHT))
7809 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7810 else if (FAKELIGHT_ENABLED)
7812 // no modellight if using fakelight for the map
7814 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7816 // pick a model lighting mode
7817 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7818 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7820 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7822 if (rsurface.ent_flags & RENDER_ADDITIVE)
7823 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7824 else if (t->currentalpha < 1)
7825 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7826 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7827 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7828 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7829 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7830 if (t->backgroundnumskinframes)
7831 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7832 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7834 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7835 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7838 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7839 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7841 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7842 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7844 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7845 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7847 // there is no tcmod
7848 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7850 t->currenttexmatrix = r_waterscrollmatrix;
7851 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7853 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7855 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7856 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7859 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7860 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7861 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7862 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7864 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7865 if (t->currentskinframe->qpixels)
7866 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7867 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7868 if (!t->basetexture)
7869 t->basetexture = r_texture_notexture;
7870 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7871 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7872 t->nmaptexture = t->currentskinframe->nmap;
7873 if (!t->nmaptexture)
7874 t->nmaptexture = r_texture_blanknormalmap;
7875 t->glosstexture = r_texture_black;
7876 t->glowtexture = t->currentskinframe->glow;
7877 t->fogtexture = t->currentskinframe->fog;
7878 t->reflectmasktexture = t->currentskinframe->reflect;
7879 if (t->backgroundnumskinframes)
7881 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7882 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7883 t->backgroundglosstexture = r_texture_black;
7884 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7885 if (!t->backgroundnmaptexture)
7886 t->backgroundnmaptexture = r_texture_blanknormalmap;
7890 t->backgroundbasetexture = r_texture_white;
7891 t->backgroundnmaptexture = r_texture_blanknormalmap;
7892 t->backgroundglosstexture = r_texture_black;
7893 t->backgroundglowtexture = NULL;
7895 t->specularpower = r_shadow_glossexponent.value;
7896 // TODO: store reference values for these in the texture?
7897 t->specularscale = 0;
7898 if (r_shadow_gloss.integer > 0)
7900 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7902 if (r_shadow_glossintensity.value > 0)
7904 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7905 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7906 t->specularscale = r_shadow_glossintensity.value;
7909 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7911 t->glosstexture = r_texture_white;
7912 t->backgroundglosstexture = r_texture_white;
7913 t->specularscale = r_shadow_gloss2intensity.value;
7914 t->specularpower = r_shadow_gloss2exponent.value;
7917 t->specularscale *= t->specularscalemod;
7918 t->specularpower *= t->specularpowermod;
7919 t->rtlightambient = 0;
7921 // lightmaps mode looks bad with dlights using actual texturing, so turn
7922 // off the colormap and glossmap, but leave the normalmap on as it still
7923 // accurately represents the shading involved
7924 if (gl_lightmaps.integer)
7926 t->basetexture = r_texture_grey128;
7927 t->pantstexture = r_texture_black;
7928 t->shirttexture = r_texture_black;
7929 t->nmaptexture = r_texture_blanknormalmap;
7930 t->glosstexture = r_texture_black;
7931 t->glowtexture = NULL;
7932 t->fogtexture = NULL;
7933 t->reflectmasktexture = NULL;
7934 t->backgroundbasetexture = NULL;
7935 t->backgroundnmaptexture = r_texture_blanknormalmap;
7936 t->backgroundglosstexture = r_texture_black;
7937 t->backgroundglowtexture = NULL;
7938 t->specularscale = 0;
7939 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7942 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7943 VectorClear(t->dlightcolor);
7944 t->currentnumlayers = 0;
7945 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7947 int blendfunc1, blendfunc2;
7949 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7951 blendfunc1 = GL_SRC_ALPHA;
7952 blendfunc2 = GL_ONE;
7954 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7956 blendfunc1 = GL_SRC_ALPHA;
7957 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7959 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7961 blendfunc1 = t->customblendfunc[0];
7962 blendfunc2 = t->customblendfunc[1];
7966 blendfunc1 = GL_ONE;
7967 blendfunc2 = GL_ZERO;
7969 // don't colormod evilblend textures
7970 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7971 VectorSet(t->lightmapcolor, 1, 1, 1);
7972 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7973 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7975 // fullbright is not affected by r_refdef.lightmapintensity
7976 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]);
7977 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7978 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]);
7979 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7980 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]);
7984 vec3_t ambientcolor;
7986 // set the color tint used for lights affecting this surface
7987 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7989 // q3bsp has no lightmap updates, so the lightstylevalue that
7990 // would normally be baked into the lightmap must be
7991 // applied to the color
7992 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7993 if (model->type == mod_brushq3)
7994 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7995 colorscale *= r_refdef.lightmapintensity;
7996 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7997 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7998 // basic lit geometry
7999 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]);
8000 // add pants/shirt if needed
8001 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8002 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]);
8003 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8004 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]);
8005 // now add ambient passes if needed
8006 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8008 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]);
8009 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8010 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]);
8011 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8012 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]);
8015 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8016 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]);
8017 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8019 // if this is opaque use alpha blend which will darken the earlier
8022 // if this is an alpha blended material, all the earlier passes
8023 // were darkened by fog already, so we only need to add the fog
8024 // color ontop through the fog mask texture
8026 // if this is an additive blended material, all the earlier passes
8027 // were darkened by fog already, and we should not add fog color
8028 // (because the background was not darkened, there is no fog color
8029 // that was lost behind it).
8030 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]);
8034 return t->currentframe;
8037 rsurfacestate_t rsurface;
8039 void RSurf_ActiveWorldEntity(void)
8041 dp_model_t *model = r_refdef.scene.worldmodel;
8042 //if (rsurface.entity == r_refdef.scene.worldentity)
8044 rsurface.entity = r_refdef.scene.worldentity;
8045 rsurface.skeleton = NULL;
8046 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8047 rsurface.ent_skinnum = 0;
8048 rsurface.ent_qwskin = -1;
8049 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8050 rsurface.shadertime = r_refdef.scene.time;
8051 rsurface.matrix = identitymatrix;
8052 rsurface.inversematrix = identitymatrix;
8053 rsurface.matrixscale = 1;
8054 rsurface.inversematrixscale = 1;
8055 R_EntityMatrix(&identitymatrix);
8056 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8057 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8058 rsurface.fograngerecip = r_refdef.fograngerecip;
8059 rsurface.fogheightfade = r_refdef.fogheightfade;
8060 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8061 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8062 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8063 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8064 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8065 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8066 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8067 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8068 rsurface.colormod[3] = 1;
8069 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);
8070 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8071 rsurface.frameblend[0].lerp = 1;
8072 rsurface.ent_alttextures = false;
8073 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8074 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8075 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8076 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8077 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8078 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8079 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8080 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8081 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8082 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8083 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8084 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8085 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8086 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8087 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8088 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8089 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8090 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8091 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8092 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8093 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8094 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8095 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8096 rsurface.modelelement3i = model->surfmesh.data_element3i;
8097 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8098 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8099 rsurface.modelelement3s = model->surfmesh.data_element3s;
8100 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8101 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8102 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8103 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8104 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8105 rsurface.modelsurfaces = model->data_surfaces;
8106 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8107 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8108 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8109 rsurface.modelgeneratedvertex = false;
8110 rsurface.batchgeneratedvertex = false;
8111 rsurface.batchfirstvertex = 0;
8112 rsurface.batchnumvertices = 0;
8113 rsurface.batchfirsttriangle = 0;
8114 rsurface.batchnumtriangles = 0;
8115 rsurface.batchvertex3f = NULL;
8116 rsurface.batchvertex3f_vertexbuffer = NULL;
8117 rsurface.batchvertex3f_bufferoffset = 0;
8118 rsurface.batchsvector3f = NULL;
8119 rsurface.batchsvector3f_vertexbuffer = NULL;
8120 rsurface.batchsvector3f_bufferoffset = 0;
8121 rsurface.batchtvector3f = NULL;
8122 rsurface.batchtvector3f_vertexbuffer = NULL;
8123 rsurface.batchtvector3f_bufferoffset = 0;
8124 rsurface.batchnormal3f = NULL;
8125 rsurface.batchnormal3f_vertexbuffer = NULL;
8126 rsurface.batchnormal3f_bufferoffset = 0;
8127 rsurface.batchlightmapcolor4f = NULL;
8128 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8129 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8130 rsurface.batchtexcoordtexture2f = NULL;
8131 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8132 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8133 rsurface.batchtexcoordlightmap2f = NULL;
8134 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8135 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8136 rsurface.batchvertexmesh = NULL;
8137 rsurface.batchvertexmeshbuffer = NULL;
8138 rsurface.batchvertex3fbuffer = NULL;
8139 rsurface.batchelement3i = NULL;
8140 rsurface.batchelement3i_indexbuffer = NULL;
8141 rsurface.batchelement3i_bufferoffset = 0;
8142 rsurface.batchelement3s = NULL;
8143 rsurface.batchelement3s_indexbuffer = NULL;
8144 rsurface.batchelement3s_bufferoffset = 0;
8145 rsurface.passcolor4f = NULL;
8146 rsurface.passcolor4f_vertexbuffer = NULL;
8147 rsurface.passcolor4f_bufferoffset = 0;
8150 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8152 dp_model_t *model = ent->model;
8153 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8155 rsurface.entity = (entity_render_t *)ent;
8156 rsurface.skeleton = ent->skeleton;
8157 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8158 rsurface.ent_skinnum = ent->skinnum;
8159 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;
8160 rsurface.ent_flags = ent->flags;
8161 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8162 rsurface.matrix = ent->matrix;
8163 rsurface.inversematrix = ent->inversematrix;
8164 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8165 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8166 R_EntityMatrix(&rsurface.matrix);
8167 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8168 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8169 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8170 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8171 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8172 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8173 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8174 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8175 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8176 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8177 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8178 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8179 rsurface.colormod[3] = ent->alpha;
8180 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8181 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8182 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8183 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8184 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8185 if (ent->model->brush.submodel && !prepass)
8187 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8188 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8190 if (model->surfmesh.isanimated && model->AnimateVertices)
8192 if (ent->animcache_vertex3f)
8194 rsurface.modelvertex3f = ent->animcache_vertex3f;
8195 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8196 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8197 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8198 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8199 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8200 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8202 else if (wanttangents)
8204 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8205 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8206 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8207 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8208 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8209 rsurface.modelvertexmesh = NULL;
8210 rsurface.modelvertexmeshbuffer = NULL;
8211 rsurface.modelvertex3fbuffer = NULL;
8213 else if (wantnormals)
8215 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8216 rsurface.modelsvector3f = NULL;
8217 rsurface.modeltvector3f = NULL;
8218 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8219 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8220 rsurface.modelvertexmesh = NULL;
8221 rsurface.modelvertexmeshbuffer = NULL;
8222 rsurface.modelvertex3fbuffer = NULL;
8226 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8227 rsurface.modelsvector3f = NULL;
8228 rsurface.modeltvector3f = NULL;
8229 rsurface.modelnormal3f = NULL;
8230 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8231 rsurface.modelvertexmesh = NULL;
8232 rsurface.modelvertexmeshbuffer = NULL;
8233 rsurface.modelvertex3fbuffer = NULL;
8235 rsurface.modelvertex3f_vertexbuffer = 0;
8236 rsurface.modelvertex3f_bufferoffset = 0;
8237 rsurface.modelsvector3f_vertexbuffer = 0;
8238 rsurface.modelsvector3f_bufferoffset = 0;
8239 rsurface.modeltvector3f_vertexbuffer = 0;
8240 rsurface.modeltvector3f_bufferoffset = 0;
8241 rsurface.modelnormal3f_vertexbuffer = 0;
8242 rsurface.modelnormal3f_bufferoffset = 0;
8243 rsurface.modelgeneratedvertex = true;
8247 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8248 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8249 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8250 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8251 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8252 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8253 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8254 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8255 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8256 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8257 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8258 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8259 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8260 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8261 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8262 rsurface.modelgeneratedvertex = false;
8264 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8265 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8266 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8267 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8268 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8269 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8270 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8271 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8272 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8273 rsurface.modelelement3i = model->surfmesh.data_element3i;
8274 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8275 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8276 rsurface.modelelement3s = model->surfmesh.data_element3s;
8277 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8278 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8279 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8280 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8281 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8282 rsurface.modelsurfaces = model->data_surfaces;
8283 rsurface.batchgeneratedvertex = false;
8284 rsurface.batchfirstvertex = 0;
8285 rsurface.batchnumvertices = 0;
8286 rsurface.batchfirsttriangle = 0;
8287 rsurface.batchnumtriangles = 0;
8288 rsurface.batchvertex3f = NULL;
8289 rsurface.batchvertex3f_vertexbuffer = NULL;
8290 rsurface.batchvertex3f_bufferoffset = 0;
8291 rsurface.batchsvector3f = NULL;
8292 rsurface.batchsvector3f_vertexbuffer = NULL;
8293 rsurface.batchsvector3f_bufferoffset = 0;
8294 rsurface.batchtvector3f = NULL;
8295 rsurface.batchtvector3f_vertexbuffer = NULL;
8296 rsurface.batchtvector3f_bufferoffset = 0;
8297 rsurface.batchnormal3f = NULL;
8298 rsurface.batchnormal3f_vertexbuffer = NULL;
8299 rsurface.batchnormal3f_bufferoffset = 0;
8300 rsurface.batchlightmapcolor4f = NULL;
8301 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8302 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8303 rsurface.batchtexcoordtexture2f = NULL;
8304 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8305 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8306 rsurface.batchtexcoordlightmap2f = NULL;
8307 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8308 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8309 rsurface.batchvertexmesh = NULL;
8310 rsurface.batchvertexmeshbuffer = NULL;
8311 rsurface.batchvertex3fbuffer = NULL;
8312 rsurface.batchelement3i = NULL;
8313 rsurface.batchelement3i_indexbuffer = NULL;
8314 rsurface.batchelement3i_bufferoffset = 0;
8315 rsurface.batchelement3s = NULL;
8316 rsurface.batchelement3s_indexbuffer = NULL;
8317 rsurface.batchelement3s_bufferoffset = 0;
8318 rsurface.passcolor4f = NULL;
8319 rsurface.passcolor4f_vertexbuffer = NULL;
8320 rsurface.passcolor4f_bufferoffset = 0;
8323 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)
8325 rsurface.entity = r_refdef.scene.worldentity;
8326 rsurface.skeleton = NULL;
8327 rsurface.ent_skinnum = 0;
8328 rsurface.ent_qwskin = -1;
8329 rsurface.ent_flags = entflags;
8330 rsurface.shadertime = r_refdef.scene.time - shadertime;
8331 rsurface.modelnumvertices = numvertices;
8332 rsurface.modelnumtriangles = numtriangles;
8333 rsurface.matrix = *matrix;
8334 rsurface.inversematrix = *inversematrix;
8335 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8336 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8337 R_EntityMatrix(&rsurface.matrix);
8338 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8339 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8340 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8341 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8342 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8343 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8344 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8345 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8346 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8347 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8348 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8349 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8350 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);
8351 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8352 rsurface.frameblend[0].lerp = 1;
8353 rsurface.ent_alttextures = false;
8354 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8355 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8358 rsurface.modelvertex3f = (float *)vertex3f;
8359 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8360 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8361 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8363 else if (wantnormals)
8365 rsurface.modelvertex3f = (float *)vertex3f;
8366 rsurface.modelsvector3f = NULL;
8367 rsurface.modeltvector3f = NULL;
8368 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8372 rsurface.modelvertex3f = (float *)vertex3f;
8373 rsurface.modelsvector3f = NULL;
8374 rsurface.modeltvector3f = NULL;
8375 rsurface.modelnormal3f = NULL;
8377 rsurface.modelvertexmesh = NULL;
8378 rsurface.modelvertexmeshbuffer = NULL;
8379 rsurface.modelvertex3fbuffer = NULL;
8380 rsurface.modelvertex3f_vertexbuffer = 0;
8381 rsurface.modelvertex3f_bufferoffset = 0;
8382 rsurface.modelsvector3f_vertexbuffer = 0;
8383 rsurface.modelsvector3f_bufferoffset = 0;
8384 rsurface.modeltvector3f_vertexbuffer = 0;
8385 rsurface.modeltvector3f_bufferoffset = 0;
8386 rsurface.modelnormal3f_vertexbuffer = 0;
8387 rsurface.modelnormal3f_bufferoffset = 0;
8388 rsurface.modelgeneratedvertex = true;
8389 rsurface.modellightmapcolor4f = (float *)color4f;
8390 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8391 rsurface.modellightmapcolor4f_bufferoffset = 0;
8392 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8393 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8394 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8395 rsurface.modeltexcoordlightmap2f = NULL;
8396 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8397 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8398 rsurface.modelelement3i = (int *)element3i;
8399 rsurface.modelelement3i_indexbuffer = NULL;
8400 rsurface.modelelement3i_bufferoffset = 0;
8401 rsurface.modelelement3s = (unsigned short *)element3s;
8402 rsurface.modelelement3s_indexbuffer = NULL;
8403 rsurface.modelelement3s_bufferoffset = 0;
8404 rsurface.modellightmapoffsets = NULL;
8405 rsurface.modelsurfaces = NULL;
8406 rsurface.batchgeneratedvertex = false;
8407 rsurface.batchfirstvertex = 0;
8408 rsurface.batchnumvertices = 0;
8409 rsurface.batchfirsttriangle = 0;
8410 rsurface.batchnumtriangles = 0;
8411 rsurface.batchvertex3f = NULL;
8412 rsurface.batchvertex3f_vertexbuffer = NULL;
8413 rsurface.batchvertex3f_bufferoffset = 0;
8414 rsurface.batchsvector3f = NULL;
8415 rsurface.batchsvector3f_vertexbuffer = NULL;
8416 rsurface.batchsvector3f_bufferoffset = 0;
8417 rsurface.batchtvector3f = NULL;
8418 rsurface.batchtvector3f_vertexbuffer = NULL;
8419 rsurface.batchtvector3f_bufferoffset = 0;
8420 rsurface.batchnormal3f = NULL;
8421 rsurface.batchnormal3f_vertexbuffer = NULL;
8422 rsurface.batchnormal3f_bufferoffset = 0;
8423 rsurface.batchlightmapcolor4f = NULL;
8424 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8425 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8426 rsurface.batchtexcoordtexture2f = NULL;
8427 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8428 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8429 rsurface.batchtexcoordlightmap2f = NULL;
8430 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8431 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8432 rsurface.batchvertexmesh = NULL;
8433 rsurface.batchvertexmeshbuffer = NULL;
8434 rsurface.batchvertex3fbuffer = NULL;
8435 rsurface.batchelement3i = NULL;
8436 rsurface.batchelement3i_indexbuffer = NULL;
8437 rsurface.batchelement3i_bufferoffset = 0;
8438 rsurface.batchelement3s = NULL;
8439 rsurface.batchelement3s_indexbuffer = NULL;
8440 rsurface.batchelement3s_bufferoffset = 0;
8441 rsurface.passcolor4f = NULL;
8442 rsurface.passcolor4f_vertexbuffer = NULL;
8443 rsurface.passcolor4f_bufferoffset = 0;
8445 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8447 if ((wantnormals || wanttangents) && !normal3f)
8449 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8450 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8452 if (wanttangents && !svector3f)
8454 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8455 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8456 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8461 float RSurf_FogPoint(const float *v)
8463 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8464 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8465 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8466 float FogHeightFade = r_refdef.fogheightfade;
8468 unsigned int fogmasktableindex;
8469 if (r_refdef.fogplaneviewabove)
8470 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8472 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8473 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8474 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8477 float RSurf_FogVertex(const float *v)
8479 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8480 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8481 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8482 float FogHeightFade = rsurface.fogheightfade;
8484 unsigned int fogmasktableindex;
8485 if (r_refdef.fogplaneviewabove)
8486 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8488 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8489 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8490 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8493 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8496 for (i = 0;i < numelements;i++)
8497 outelement3i[i] = inelement3i[i] + adjust;
8500 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8501 extern cvar_t gl_vbo;
8502 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8510 int surfacefirsttriangle;
8511 int surfacenumtriangles;
8512 int surfacefirstvertex;
8513 int surfaceendvertex;
8514 int surfacenumvertices;
8515 int batchnumvertices;
8516 int batchnumtriangles;
8520 qboolean dynamicvertex;
8524 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8526 q3shaderinfo_deform_t *deform;
8527 const msurface_t *surface, *firstsurface;
8528 r_vertexmesh_t *vertexmesh;
8529 if (!texturenumsurfaces)
8531 // find vertex range of this surface batch
8533 firstsurface = texturesurfacelist[0];
8534 firsttriangle = firstsurface->num_firsttriangle;
8535 batchnumvertices = 0;
8536 batchnumtriangles = 0;
8537 firstvertex = endvertex = firstsurface->num_firstvertex;
8538 for (i = 0;i < texturenumsurfaces;i++)
8540 surface = texturesurfacelist[i];
8541 if (surface != firstsurface + i)
8543 surfacefirstvertex = surface->num_firstvertex;
8544 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8545 surfacenumvertices = surface->num_vertices;
8546 surfacenumtriangles = surface->num_triangles;
8547 if (firstvertex > surfacefirstvertex)
8548 firstvertex = surfacefirstvertex;
8549 if (endvertex < surfaceendvertex)
8550 endvertex = surfaceendvertex;
8551 batchnumvertices += surfacenumvertices;
8552 batchnumtriangles += surfacenumtriangles;
8555 // we now know the vertex range used, and if there are any gaps in it
8556 rsurface.batchfirstvertex = firstvertex;
8557 rsurface.batchnumvertices = endvertex - firstvertex;
8558 rsurface.batchfirsttriangle = firsttriangle;
8559 rsurface.batchnumtriangles = batchnumtriangles;
8561 // this variable holds flags for which properties have been updated that
8562 // may require regenerating vertexmesh array...
8565 // check if any dynamic vertex processing must occur
8566 dynamicvertex = false;
8568 // if there is a chance of animated vertex colors, it's a dynamic batch
8569 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8571 dynamicvertex = true;
8572 batchneed |= BATCHNEED_NOGAPS;
8573 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8576 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8578 switch (deform->deform)
8581 case Q3DEFORM_PROJECTIONSHADOW:
8582 case Q3DEFORM_TEXT0:
8583 case Q3DEFORM_TEXT1:
8584 case Q3DEFORM_TEXT2:
8585 case Q3DEFORM_TEXT3:
8586 case Q3DEFORM_TEXT4:
8587 case Q3DEFORM_TEXT5:
8588 case Q3DEFORM_TEXT6:
8589 case Q3DEFORM_TEXT7:
8592 case Q3DEFORM_AUTOSPRITE:
8593 dynamicvertex = true;
8594 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8595 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8597 case Q3DEFORM_AUTOSPRITE2:
8598 dynamicvertex = true;
8599 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8600 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8602 case Q3DEFORM_NORMAL:
8603 dynamicvertex = true;
8604 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8605 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8608 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8609 break; // if wavefunc is a nop, ignore this transform
8610 dynamicvertex = true;
8611 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8612 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8614 case Q3DEFORM_BULGE:
8615 dynamicvertex = true;
8616 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8617 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8620 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8621 break; // if wavefunc is a nop, ignore this transform
8622 dynamicvertex = true;
8623 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8624 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8628 switch(rsurface.texture->tcgen.tcgen)
8631 case Q3TCGEN_TEXTURE:
8633 case Q3TCGEN_LIGHTMAP:
8634 dynamicvertex = true;
8635 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8636 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8638 case Q3TCGEN_VECTOR:
8639 dynamicvertex = true;
8640 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8641 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8643 case Q3TCGEN_ENVIRONMENT:
8644 dynamicvertex = true;
8645 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8646 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8649 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8651 dynamicvertex = true;
8652 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8653 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8656 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8658 dynamicvertex = true;
8659 batchneed |= BATCHNEED_NOGAPS;
8660 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8663 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8665 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8666 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8667 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8668 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8669 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8670 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8671 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8674 // when the model data has no vertex buffer (dynamic mesh), we need to
8676 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8677 batchneed |= BATCHNEED_NOGAPS;
8679 // if needsupdate, we have to do a dynamic vertex batch for sure
8680 if (needsupdate & batchneed)
8681 dynamicvertex = true;
8683 // see if we need to build vertexmesh from arrays
8684 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8685 dynamicvertex = true;
8687 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8688 // also some drivers strongly dislike firstvertex
8689 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8690 dynamicvertex = true;
8692 rsurface.batchvertex3f = rsurface.modelvertex3f;
8693 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8694 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8695 rsurface.batchsvector3f = rsurface.modelsvector3f;
8696 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8697 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8698 rsurface.batchtvector3f = rsurface.modeltvector3f;
8699 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8700 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8701 rsurface.batchnormal3f = rsurface.modelnormal3f;
8702 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8703 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8704 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8705 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8706 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8707 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8708 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8709 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8710 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8711 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8712 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8713 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8714 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8715 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8716 rsurface.batchelement3i = rsurface.modelelement3i;
8717 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8718 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8719 rsurface.batchelement3s = rsurface.modelelement3s;
8720 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8721 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8723 // if any dynamic vertex processing has to occur in software, we copy the
8724 // entire surface list together before processing to rebase the vertices
8725 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8727 // if any gaps exist and we do not have a static vertex buffer, we have to
8728 // copy the surface list together to avoid wasting upload bandwidth on the
8729 // vertices in the gaps.
8731 // if gaps exist and we have a static vertex buffer, we still have to
8732 // combine the index buffer ranges into one dynamic index buffer.
8734 // in all cases we end up with data that can be drawn in one call.
8738 // static vertex data, just set pointers...
8739 rsurface.batchgeneratedvertex = false;
8740 // if there are gaps, we want to build a combined index buffer,
8741 // otherwise use the original static buffer with an appropriate offset
8744 // build a new triangle elements array for this batch
8745 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8746 rsurface.batchfirsttriangle = 0;
8748 for (i = 0;i < texturenumsurfaces;i++)
8750 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8751 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8752 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8753 numtriangles += surfacenumtriangles;
8755 rsurface.batchelement3i_indexbuffer = NULL;
8756 rsurface.batchelement3i_bufferoffset = 0;
8757 rsurface.batchelement3s = NULL;
8758 rsurface.batchelement3s_indexbuffer = NULL;
8759 rsurface.batchelement3s_bufferoffset = 0;
8760 if (endvertex <= 65536)
8762 // make a 16bit (unsigned short) index array if possible
8763 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8764 for (i = 0;i < numtriangles*3;i++)
8765 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8771 // something needs software processing, do it for real...
8772 // we only directly handle separate array data in this case and then
8773 // generate interleaved data if needed...
8774 rsurface.batchgeneratedvertex = true;
8776 // now copy the vertex data into a combined array and make an index array
8777 // (this is what Quake3 does all the time)
8778 //if (gaps || rsurface.batchfirstvertex)
8780 rsurface.batchvertex3fbuffer = NULL;
8781 rsurface.batchvertexmesh = NULL;
8782 rsurface.batchvertexmeshbuffer = NULL;
8783 rsurface.batchvertex3f = NULL;
8784 rsurface.batchvertex3f_vertexbuffer = NULL;
8785 rsurface.batchvertex3f_bufferoffset = 0;
8786 rsurface.batchsvector3f = NULL;
8787 rsurface.batchsvector3f_vertexbuffer = NULL;
8788 rsurface.batchsvector3f_bufferoffset = 0;
8789 rsurface.batchtvector3f = NULL;
8790 rsurface.batchtvector3f_vertexbuffer = NULL;
8791 rsurface.batchtvector3f_bufferoffset = 0;
8792 rsurface.batchnormal3f = NULL;
8793 rsurface.batchnormal3f_vertexbuffer = NULL;
8794 rsurface.batchnormal3f_bufferoffset = 0;
8795 rsurface.batchlightmapcolor4f = NULL;
8796 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8797 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8798 rsurface.batchtexcoordtexture2f = NULL;
8799 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8800 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8801 rsurface.batchtexcoordlightmap2f = NULL;
8802 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8803 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8804 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8805 rsurface.batchelement3i_indexbuffer = NULL;
8806 rsurface.batchelement3i_bufferoffset = 0;
8807 rsurface.batchelement3s = NULL;
8808 rsurface.batchelement3s_indexbuffer = NULL;
8809 rsurface.batchelement3s_bufferoffset = 0;
8810 // we'll only be setting up certain arrays as needed
8811 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8812 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8813 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8814 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8815 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8816 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8817 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8819 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8820 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8822 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8823 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8824 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8825 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8826 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8827 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8830 for (i = 0;i < texturenumsurfaces;i++)
8832 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8833 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8834 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8835 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8836 // copy only the data requested
8837 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8838 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8839 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8841 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8843 if (rsurface.batchvertex3f)
8844 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8846 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8848 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8850 if (rsurface.modelnormal3f)
8851 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8853 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8855 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8857 if (rsurface.modelsvector3f)
8859 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8860 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8864 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8865 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8868 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8870 if (rsurface.modellightmapcolor4f)
8871 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8873 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8875 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8877 if (rsurface.modeltexcoordtexture2f)
8878 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8880 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8882 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8884 if (rsurface.modeltexcoordlightmap2f)
8885 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8887 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8890 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8891 numvertices += surfacenumvertices;
8892 numtriangles += surfacenumtriangles;
8895 // generate a 16bit index array as well if possible
8896 // (in general, dynamic batches fit)
8897 if (numvertices <= 65536)
8899 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8900 for (i = 0;i < numtriangles*3;i++)
8901 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8904 // since we've copied everything, the batch now starts at 0
8905 rsurface.batchfirstvertex = 0;
8906 rsurface.batchnumvertices = batchnumvertices;
8907 rsurface.batchfirsttriangle = 0;
8908 rsurface.batchnumtriangles = batchnumtriangles;
8911 // q1bsp surfaces rendered in vertex color mode have to have colors
8912 // calculated based on lightstyles
8913 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8915 // generate color arrays for the surfaces in this list
8920 const unsigned char *lm;
8921 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8922 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8923 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8925 for (i = 0;i < texturenumsurfaces;i++)
8927 surface = texturesurfacelist[i];
8928 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8929 surfacenumvertices = surface->num_vertices;
8930 if (surface->lightmapinfo->samples)
8932 for (j = 0;j < surfacenumvertices;j++)
8934 lm = surface->lightmapinfo->samples + offsets[j];
8935 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8936 VectorScale(lm, scale, c);
8937 if (surface->lightmapinfo->styles[1] != 255)
8939 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8941 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8942 VectorMA(c, scale, lm, c);
8943 if (surface->lightmapinfo->styles[2] != 255)
8946 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8947 VectorMA(c, scale, lm, c);
8948 if (surface->lightmapinfo->styles[3] != 255)
8951 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8952 VectorMA(c, scale, lm, c);
8959 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);
8965 for (j = 0;j < surfacenumvertices;j++)
8967 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8974 // if vertices are deformed (sprite flares and things in maps, possibly
8975 // water waves, bulges and other deformations), modify the copied vertices
8977 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8979 switch (deform->deform)
8982 case Q3DEFORM_PROJECTIONSHADOW:
8983 case Q3DEFORM_TEXT0:
8984 case Q3DEFORM_TEXT1:
8985 case Q3DEFORM_TEXT2:
8986 case Q3DEFORM_TEXT3:
8987 case Q3DEFORM_TEXT4:
8988 case Q3DEFORM_TEXT5:
8989 case Q3DEFORM_TEXT6:
8990 case Q3DEFORM_TEXT7:
8993 case Q3DEFORM_AUTOSPRITE:
8994 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8995 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8996 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8997 VectorNormalize(newforward);
8998 VectorNormalize(newright);
8999 VectorNormalize(newup);
9000 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9001 // rsurface.batchvertex3f_vertexbuffer = NULL;
9002 // rsurface.batchvertex3f_bufferoffset = 0;
9003 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9004 // rsurface.batchsvector3f_vertexbuffer = NULL;
9005 // rsurface.batchsvector3f_bufferoffset = 0;
9006 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9007 // rsurface.batchtvector3f_vertexbuffer = NULL;
9008 // rsurface.batchtvector3f_bufferoffset = 0;
9009 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9010 // rsurface.batchnormal3f_vertexbuffer = NULL;
9011 // rsurface.batchnormal3f_bufferoffset = 0;
9012 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9013 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9014 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9015 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9016 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);
9017 // a single autosprite surface can contain multiple sprites...
9018 for (j = 0;j < batchnumvertices - 3;j += 4)
9020 VectorClear(center);
9021 for (i = 0;i < 4;i++)
9022 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9023 VectorScale(center, 0.25f, center);
9024 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9025 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9026 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9027 for (i = 0;i < 4;i++)
9029 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9030 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9033 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9034 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9035 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);
9037 case Q3DEFORM_AUTOSPRITE2:
9038 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9039 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9040 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9041 VectorNormalize(newforward);
9042 VectorNormalize(newright);
9043 VectorNormalize(newup);
9044 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9045 // rsurface.batchvertex3f_vertexbuffer = NULL;
9046 // rsurface.batchvertex3f_bufferoffset = 0;
9048 const float *v1, *v2;
9058 memset(shortest, 0, sizeof(shortest));
9059 // a single autosprite surface can contain multiple sprites...
9060 for (j = 0;j < batchnumvertices - 3;j += 4)
9062 VectorClear(center);
9063 for (i = 0;i < 4;i++)
9064 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9065 VectorScale(center, 0.25f, center);
9066 // find the two shortest edges, then use them to define the
9067 // axis vectors for rotating around the central axis
9068 for (i = 0;i < 6;i++)
9070 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9071 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9072 l = VectorDistance2(v1, v2);
9073 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9075 l += (1.0f / 1024.0f);
9076 if (shortest[0].length2 > l || i == 0)
9078 shortest[1] = shortest[0];
9079 shortest[0].length2 = l;
9080 shortest[0].v1 = v1;
9081 shortest[0].v2 = v2;
9083 else if (shortest[1].length2 > l || i == 1)
9085 shortest[1].length2 = l;
9086 shortest[1].v1 = v1;
9087 shortest[1].v2 = v2;
9090 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9091 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9092 // this calculates the right vector from the shortest edge
9093 // and the up vector from the edge midpoints
9094 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9095 VectorNormalize(right);
9096 VectorSubtract(end, start, up);
9097 VectorNormalize(up);
9098 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9099 VectorSubtract(rsurface.localvieworigin, center, forward);
9100 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9101 VectorNegate(forward, forward);
9102 VectorReflect(forward, 0, up, forward);
9103 VectorNormalize(forward);
9104 CrossProduct(up, forward, newright);
9105 VectorNormalize(newright);
9106 // rotate the quad around the up axis vector, this is made
9107 // especially easy by the fact we know the quad is flat,
9108 // so we only have to subtract the center position and
9109 // measure distance along the right vector, and then
9110 // multiply that by the newright vector and add back the
9112 // we also need to subtract the old position to undo the
9113 // displacement from the center, which we do with a
9114 // DotProduct, the subtraction/addition of center is also
9115 // optimized into DotProducts here
9116 l = DotProduct(right, center);
9117 for (i = 0;i < 4;i++)
9119 v1 = rsurface.batchvertex3f + 3*(j+i);
9120 f = DotProduct(right, v1) - l;
9121 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9125 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9127 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9128 // rsurface.batchnormal3f_vertexbuffer = NULL;
9129 // rsurface.batchnormal3f_bufferoffset = 0;
9130 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9132 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9134 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9135 // rsurface.batchsvector3f_vertexbuffer = NULL;
9136 // rsurface.batchsvector3f_bufferoffset = 0;
9137 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9138 // rsurface.batchtvector3f_vertexbuffer = NULL;
9139 // rsurface.batchtvector3f_bufferoffset = 0;
9140 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);
9143 case Q3DEFORM_NORMAL:
9144 // deform the normals to make reflections wavey
9145 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9146 rsurface.batchnormal3f_vertexbuffer = NULL;
9147 rsurface.batchnormal3f_bufferoffset = 0;
9148 for (j = 0;j < batchnumvertices;j++)
9151 float *normal = rsurface.batchnormal3f + 3*j;
9152 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9153 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9154 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9155 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9156 VectorNormalize(normal);
9158 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9160 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9161 // rsurface.batchsvector3f_vertexbuffer = NULL;
9162 // rsurface.batchsvector3f_bufferoffset = 0;
9163 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9164 // rsurface.batchtvector3f_vertexbuffer = NULL;
9165 // rsurface.batchtvector3f_bufferoffset = 0;
9166 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);
9170 // deform vertex array to make wavey water and flags and such
9171 waveparms[0] = deform->waveparms[0];
9172 waveparms[1] = deform->waveparms[1];
9173 waveparms[2] = deform->waveparms[2];
9174 waveparms[3] = deform->waveparms[3];
9175 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9176 break; // if wavefunc is a nop, don't make a dynamic vertex array
9177 // this is how a divisor of vertex influence on deformation
9178 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9179 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9180 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9181 // rsurface.batchvertex3f_vertexbuffer = NULL;
9182 // rsurface.batchvertex3f_bufferoffset = 0;
9183 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9184 // rsurface.batchnormal3f_vertexbuffer = NULL;
9185 // rsurface.batchnormal3f_bufferoffset = 0;
9186 for (j = 0;j < batchnumvertices;j++)
9188 // if the wavefunc depends on time, evaluate it per-vertex
9191 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9192 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9194 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9196 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9197 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9198 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9200 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9201 // rsurface.batchsvector3f_vertexbuffer = NULL;
9202 // rsurface.batchsvector3f_bufferoffset = 0;
9203 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9204 // rsurface.batchtvector3f_vertexbuffer = NULL;
9205 // rsurface.batchtvector3f_bufferoffset = 0;
9206 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);
9209 case Q3DEFORM_BULGE:
9210 // deform vertex array to make the surface have moving bulges
9211 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9212 // rsurface.batchvertex3f_vertexbuffer = NULL;
9213 // rsurface.batchvertex3f_bufferoffset = 0;
9214 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9215 // rsurface.batchnormal3f_vertexbuffer = NULL;
9216 // rsurface.batchnormal3f_bufferoffset = 0;
9217 for (j = 0;j < batchnumvertices;j++)
9219 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9220 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9222 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9223 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9224 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9226 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9227 // rsurface.batchsvector3f_vertexbuffer = NULL;
9228 // rsurface.batchsvector3f_bufferoffset = 0;
9229 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9230 // rsurface.batchtvector3f_vertexbuffer = NULL;
9231 // rsurface.batchtvector3f_bufferoffset = 0;
9232 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);
9236 // deform vertex array
9237 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9238 break; // if wavefunc is a nop, don't make a dynamic vertex array
9239 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9240 VectorScale(deform->parms, scale, waveparms);
9241 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9242 // rsurface.batchvertex3f_vertexbuffer = NULL;
9243 // rsurface.batchvertex3f_bufferoffset = 0;
9244 for (j = 0;j < batchnumvertices;j++)
9245 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9250 // generate texcoords based on the chosen texcoord source
9251 switch(rsurface.texture->tcgen.tcgen)
9254 case Q3TCGEN_TEXTURE:
9256 case Q3TCGEN_LIGHTMAP:
9257 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9258 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9259 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9260 if (rsurface.batchtexcoordlightmap2f)
9261 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9263 case Q3TCGEN_VECTOR:
9264 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9265 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9266 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9267 for (j = 0;j < batchnumvertices;j++)
9269 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9270 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9273 case Q3TCGEN_ENVIRONMENT:
9274 // make environment reflections using a spheremap
9275 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9276 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9277 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9278 for (j = 0;j < batchnumvertices;j++)
9280 // identical to Q3A's method, but executed in worldspace so
9281 // carried models can be shiny too
9283 float viewer[3], d, reflected[3], worldreflected[3];
9285 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9286 // VectorNormalize(viewer);
9288 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9290 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9291 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9292 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9293 // note: this is proportinal to viewer, so we can normalize later
9295 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9296 VectorNormalize(worldreflected);
9298 // note: this sphere map only uses world x and z!
9299 // so positive and negative y will LOOK THE SAME.
9300 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9301 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9305 // the only tcmod that needs software vertex processing is turbulent, so
9306 // check for it here and apply the changes if needed
9307 // and we only support that as the first one
9308 // (handling a mixture of turbulent and other tcmods would be problematic
9309 // without punting it entirely to a software path)
9310 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9312 amplitude = rsurface.texture->tcmods[0].parms[1];
9313 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9314 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9315 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9316 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9317 for (j = 0;j < batchnumvertices;j++)
9319 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);
9320 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9324 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9326 // convert the modified arrays to vertex structs
9327 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9328 // rsurface.batchvertexmeshbuffer = NULL;
9329 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9330 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9331 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9332 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9333 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9334 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9335 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9337 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9339 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9340 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9343 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9344 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9345 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9346 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9347 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9348 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9349 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9350 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9351 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9355 void RSurf_DrawBatch(void)
9357 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9358 // through the pipeline, killing it earlier in the pipeline would have
9359 // per-surface overhead rather than per-batch overhead, so it's best to
9360 // reject it here, before it hits glDraw.
9361 if (rsurface.batchnumtriangles == 0)
9364 // batch debugging code
9365 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9371 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9372 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9375 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9377 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9379 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9380 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);
9387 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);
9390 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9392 // pick the closest matching water plane
9393 int planeindex, vertexindex, bestplaneindex = -1;
9397 r_waterstate_waterplane_t *p;
9398 qboolean prepared = false;
9400 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9402 if(p->camera_entity != rsurface.texture->camera_entity)
9407 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9409 if(rsurface.batchnumvertices == 0)
9412 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9414 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9415 d += fabs(PlaneDiff(vert, &p->plane));
9417 if (bestd > d || bestplaneindex < 0)
9420 bestplaneindex = planeindex;
9423 return bestplaneindex;
9424 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9425 // this situation though, as it might be better to render single larger
9426 // batches with useless stuff (backface culled for example) than to
9427 // render multiple smaller batches
9430 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9433 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9434 rsurface.passcolor4f_vertexbuffer = 0;
9435 rsurface.passcolor4f_bufferoffset = 0;
9436 for (i = 0;i < rsurface.batchnumvertices;i++)
9437 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9440 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9447 if (rsurface.passcolor4f)
9449 // generate color arrays
9450 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9451 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9452 rsurface.passcolor4f_vertexbuffer = 0;
9453 rsurface.passcolor4f_bufferoffset = 0;
9454 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9456 f = RSurf_FogVertex(v);
9465 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9466 rsurface.passcolor4f_vertexbuffer = 0;
9467 rsurface.passcolor4f_bufferoffset = 0;
9468 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9470 f = RSurf_FogVertex(v);
9479 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9486 if (!rsurface.passcolor4f)
9488 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9489 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9490 rsurface.passcolor4f_vertexbuffer = 0;
9491 rsurface.passcolor4f_bufferoffset = 0;
9492 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)
9494 f = RSurf_FogVertex(v);
9495 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9496 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9497 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9502 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9507 if (!rsurface.passcolor4f)
9509 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9510 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9511 rsurface.passcolor4f_vertexbuffer = 0;
9512 rsurface.passcolor4f_bufferoffset = 0;
9513 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9522 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9527 if (!rsurface.passcolor4f)
9529 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9530 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9531 rsurface.passcolor4f_vertexbuffer = 0;
9532 rsurface.passcolor4f_bufferoffset = 0;
9533 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9535 c2[0] = c[0] + r_refdef.scene.ambient;
9536 c2[1] = c[1] + r_refdef.scene.ambient;
9537 c2[2] = c[2] + r_refdef.scene.ambient;
9542 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9545 rsurface.passcolor4f = NULL;
9546 rsurface.passcolor4f_vertexbuffer = 0;
9547 rsurface.passcolor4f_bufferoffset = 0;
9548 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9549 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9550 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9551 GL_Color(r, g, b, a);
9552 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9556 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9558 // TODO: optimize applyfog && applycolor case
9559 // just apply fog if necessary, and tint the fog color array if necessary
9560 rsurface.passcolor4f = NULL;
9561 rsurface.passcolor4f_vertexbuffer = 0;
9562 rsurface.passcolor4f_bufferoffset = 0;
9563 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9564 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9565 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9566 GL_Color(r, g, b, a);
9570 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9573 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9574 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9575 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9576 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9577 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9578 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9579 GL_Color(r, g, b, a);
9583 static void RSurf_DrawBatch_GL11_ClampColor(void)
9588 if (!rsurface.passcolor4f)
9590 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9592 c2[0] = bound(0.0f, c1[0], 1.0f);
9593 c2[1] = bound(0.0f, c1[1], 1.0f);
9594 c2[2] = bound(0.0f, c1[2], 1.0f);
9595 c2[3] = bound(0.0f, c1[3], 1.0f);
9599 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9609 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9610 rsurface.passcolor4f_vertexbuffer = 0;
9611 rsurface.passcolor4f_bufferoffset = 0;
9612 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)
9614 f = -DotProduct(r_refdef.view.forward, n);
9616 f = f * 0.85 + 0.15; // work around so stuff won't get black
9617 f *= r_refdef.lightmapintensity;
9618 Vector4Set(c, f, f, f, 1);
9622 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9624 RSurf_DrawBatch_GL11_ApplyFakeLight();
9625 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9626 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9627 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9628 GL_Color(r, g, b, a);
9632 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9640 vec3_t ambientcolor;
9641 vec3_t diffusecolor;
9645 VectorCopy(rsurface.modellight_lightdir, lightdir);
9646 f = 0.5f * r_refdef.lightmapintensity;
9647 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9648 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9649 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9650 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9651 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9652 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9654 if (VectorLength2(diffusecolor) > 0)
9656 // q3-style directional shading
9657 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9658 rsurface.passcolor4f_vertexbuffer = 0;
9659 rsurface.passcolor4f_bufferoffset = 0;
9660 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)
9662 if ((f = DotProduct(n, lightdir)) > 0)
9663 VectorMA(ambientcolor, f, diffusecolor, c);
9665 VectorCopy(ambientcolor, c);
9672 *applycolor = false;
9676 *r = ambientcolor[0];
9677 *g = ambientcolor[1];
9678 *b = ambientcolor[2];
9679 rsurface.passcolor4f = NULL;
9680 rsurface.passcolor4f_vertexbuffer = 0;
9681 rsurface.passcolor4f_bufferoffset = 0;
9685 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9687 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9688 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9689 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9690 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9691 GL_Color(r, g, b, a);
9695 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9703 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9704 rsurface.passcolor4f_vertexbuffer = 0;
9705 rsurface.passcolor4f_bufferoffset = 0;
9707 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9709 f = 1 - RSurf_FogVertex(v);
9717 void RSurf_SetupDepthAndCulling(void)
9719 // submodels are biased to avoid z-fighting with world surfaces that they
9720 // may be exactly overlapping (avoids z-fighting artifacts on certain
9721 // doors and things in Quake maps)
9722 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9723 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9724 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9725 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9728 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9730 // transparent sky would be ridiculous
9731 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9733 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9734 skyrenderlater = true;
9735 RSurf_SetupDepthAndCulling();
9737 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9738 // skymasking on them, and Quake3 never did sky masking (unlike
9739 // software Quake and software Quake2), so disable the sky masking
9740 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9741 // and skymasking also looks very bad when noclipping outside the
9742 // level, so don't use it then either.
9743 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9745 R_Mesh_ResetTextureState();
9746 if (skyrendermasked)
9748 R_SetupShader_DepthOrShadow(false);
9749 // depth-only (masking)
9750 GL_ColorMask(0,0,0,0);
9751 // just to make sure that braindead drivers don't draw
9752 // anything despite that colormask...
9753 GL_BlendFunc(GL_ZERO, GL_ONE);
9754 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9755 if (rsurface.batchvertex3fbuffer)
9756 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9758 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9762 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9764 GL_BlendFunc(GL_ONE, GL_ZERO);
9765 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9766 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9767 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9770 if (skyrendermasked)
9771 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9773 R_Mesh_ResetTextureState();
9774 GL_Color(1, 1, 1, 1);
9777 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9778 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9779 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9781 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9785 // render screenspace normalmap to texture
9787 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9791 // bind lightmap texture
9793 // water/refraction/reflection/camera surfaces have to be handled specially
9794 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9796 int start, end, startplaneindex;
9797 for (start = 0;start < texturenumsurfaces;start = end)
9799 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9800 if(startplaneindex < 0)
9802 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9803 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9807 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9809 // now that we have a batch using the same planeindex, render it
9810 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9812 // render water or distortion background
9814 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9816 // blend surface on top
9817 GL_DepthMask(false);
9818 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9821 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9823 // render surface with reflection texture as input
9824 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9825 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9832 // render surface batch normally
9833 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9834 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);
9838 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9840 // OpenGL 1.3 path - anything not completely ancient
9841 qboolean applycolor;
9844 const texturelayer_t *layer;
9845 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);
9846 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9848 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9851 int layertexrgbscale;
9852 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9854 if (layerindex == 0)
9858 GL_AlphaTest(false);
9859 GL_DepthFunc(GL_EQUAL);
9862 GL_DepthMask(layer->depthmask && writedepth);
9863 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9864 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9866 layertexrgbscale = 4;
9867 VectorScale(layer->color, 0.25f, layercolor);
9869 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9871 layertexrgbscale = 2;
9872 VectorScale(layer->color, 0.5f, layercolor);
9876 layertexrgbscale = 1;
9877 VectorScale(layer->color, 1.0f, layercolor);
9879 layercolor[3] = layer->color[3];
9880 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9881 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9882 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9883 switch (layer->type)
9885 case TEXTURELAYERTYPE_LITTEXTURE:
9886 // single-pass lightmapped texture with 2x rgbscale
9887 R_Mesh_TexBind(0, r_texture_white);
9888 R_Mesh_TexMatrix(0, NULL);
9889 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9890 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9891 R_Mesh_TexBind(1, layer->texture);
9892 R_Mesh_TexMatrix(1, &layer->texmatrix);
9893 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9894 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9895 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9896 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9897 else if (FAKELIGHT_ENABLED)
9898 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9899 else if (rsurface.uselightmaptexture)
9900 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9902 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9904 case TEXTURELAYERTYPE_TEXTURE:
9905 // singletexture unlit texture with transparency support
9906 R_Mesh_TexBind(0, layer->texture);
9907 R_Mesh_TexMatrix(0, &layer->texmatrix);
9908 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9909 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9910 R_Mesh_TexBind(1, 0);
9911 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9912 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9914 case TEXTURELAYERTYPE_FOG:
9915 // singletexture fogging
9918 R_Mesh_TexBind(0, layer->texture);
9919 R_Mesh_TexMatrix(0, &layer->texmatrix);
9920 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9921 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9925 R_Mesh_TexBind(0, 0);
9926 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9928 R_Mesh_TexBind(1, 0);
9929 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9930 // generate a color array for the fog pass
9931 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9932 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9936 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9939 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9941 GL_DepthFunc(GL_LEQUAL);
9942 GL_AlphaTest(false);
9946 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9948 // OpenGL 1.1 - crusty old voodoo path
9951 const texturelayer_t *layer;
9952 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);
9953 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9955 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9957 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9959 if (layerindex == 0)
9963 GL_AlphaTest(false);
9964 GL_DepthFunc(GL_EQUAL);
9967 GL_DepthMask(layer->depthmask && writedepth);
9968 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9969 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9970 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9971 switch (layer->type)
9973 case TEXTURELAYERTYPE_LITTEXTURE:
9974 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9976 // two-pass lit texture with 2x rgbscale
9977 // first the lightmap pass
9978 R_Mesh_TexBind(0, r_texture_white);
9979 R_Mesh_TexMatrix(0, NULL);
9980 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9981 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9982 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9983 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9984 else if (FAKELIGHT_ENABLED)
9985 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9986 else if (rsurface.uselightmaptexture)
9987 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9989 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9990 // then apply the texture to it
9991 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9992 R_Mesh_TexBind(0, layer->texture);
9993 R_Mesh_TexMatrix(0, &layer->texmatrix);
9994 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9995 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9996 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);
10000 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10001 R_Mesh_TexBind(0, layer->texture);
10002 R_Mesh_TexMatrix(0, &layer->texmatrix);
10003 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10004 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10005 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10006 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);
10008 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);
10011 case TEXTURELAYERTYPE_TEXTURE:
10012 // singletexture unlit texture with transparency support
10013 R_Mesh_TexBind(0, layer->texture);
10014 R_Mesh_TexMatrix(0, &layer->texmatrix);
10015 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10016 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10017 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);
10019 case TEXTURELAYERTYPE_FOG:
10020 // singletexture fogging
10021 if (layer->texture)
10023 R_Mesh_TexBind(0, layer->texture);
10024 R_Mesh_TexMatrix(0, &layer->texmatrix);
10025 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10026 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10030 R_Mesh_TexBind(0, 0);
10031 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10033 // generate a color array for the fog pass
10034 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10035 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10039 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10042 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10044 GL_DepthFunc(GL_LEQUAL);
10045 GL_AlphaTest(false);
10049 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10053 r_vertexgeneric_t *batchvertex;
10056 // R_Mesh_ResetTextureState();
10057 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10059 if(rsurface.texture && rsurface.texture->currentskinframe)
10061 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10062 c[3] *= rsurface.texture->currentalpha;
10072 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10074 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10075 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10076 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10079 // brighten it up (as texture value 127 means "unlit")
10080 c[0] *= 2 * r_refdef.view.colorscale;
10081 c[1] *= 2 * r_refdef.view.colorscale;
10082 c[2] *= 2 * r_refdef.view.colorscale;
10084 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10085 c[3] *= r_wateralpha.value;
10087 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10089 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10090 GL_DepthMask(false);
10092 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10094 GL_BlendFunc(GL_ONE, GL_ONE);
10095 GL_DepthMask(false);
10097 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10099 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10100 GL_DepthMask(false);
10102 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10104 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10105 GL_DepthMask(false);
10109 GL_BlendFunc(GL_ONE, GL_ZERO);
10110 GL_DepthMask(writedepth);
10113 if (r_showsurfaces.integer == 3)
10115 rsurface.passcolor4f = NULL;
10117 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10119 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10121 rsurface.passcolor4f = NULL;
10122 rsurface.passcolor4f_vertexbuffer = 0;
10123 rsurface.passcolor4f_bufferoffset = 0;
10125 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10127 qboolean applycolor = true;
10130 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10132 r_refdef.lightmapintensity = 1;
10133 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10134 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10136 else if (FAKELIGHT_ENABLED)
10138 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10140 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10141 RSurf_DrawBatch_GL11_ApplyFakeLight();
10142 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10146 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10148 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10149 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10150 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10153 if(!rsurface.passcolor4f)
10154 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10156 RSurf_DrawBatch_GL11_ApplyAmbient();
10157 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10158 if(r_refdef.fogenabled)
10159 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10160 RSurf_DrawBatch_GL11_ClampColor();
10162 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10163 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10166 else if (!r_refdef.view.showdebug)
10168 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10169 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10170 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10172 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10173 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10175 R_Mesh_PrepareVertices_Generic_Unlock();
10178 else if (r_showsurfaces.integer == 4)
10180 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10181 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10182 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10184 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10185 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10186 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10188 R_Mesh_PrepareVertices_Generic_Unlock();
10191 else if (r_showsurfaces.integer == 2)
10194 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10195 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10196 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10198 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10199 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10200 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10201 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10202 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10203 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10204 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10206 R_Mesh_PrepareVertices_Generic_Unlock();
10207 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10211 int texturesurfaceindex;
10213 const msurface_t *surface;
10214 float surfacecolor4f[4];
10215 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10216 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10218 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10220 surface = texturesurfacelist[texturesurfaceindex];
10221 k = (int)(((size_t)surface) / sizeof(msurface_t));
10222 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10223 for (j = 0;j < surface->num_vertices;j++)
10225 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10226 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10230 R_Mesh_PrepareVertices_Generic_Unlock();
10235 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10238 RSurf_SetupDepthAndCulling();
10239 if (r_showsurfaces.integer)
10241 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10244 switch (vid.renderpath)
10246 case RENDERPATH_GL20:
10247 case RENDERPATH_D3D9:
10248 case RENDERPATH_D3D10:
10249 case RENDERPATH_D3D11:
10250 case RENDERPATH_SOFT:
10251 case RENDERPATH_GLES2:
10252 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10254 case RENDERPATH_GL13:
10255 case RENDERPATH_GLES1:
10256 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10258 case RENDERPATH_GL11:
10259 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10265 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10268 RSurf_SetupDepthAndCulling();
10269 if (r_showsurfaces.integer)
10271 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10274 switch (vid.renderpath)
10276 case RENDERPATH_GL20:
10277 case RENDERPATH_D3D9:
10278 case RENDERPATH_D3D10:
10279 case RENDERPATH_D3D11:
10280 case RENDERPATH_SOFT:
10281 case RENDERPATH_GLES2:
10282 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10284 case RENDERPATH_GL13:
10285 case RENDERPATH_GLES1:
10286 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10288 case RENDERPATH_GL11:
10289 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10295 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10298 int texturenumsurfaces, endsurface;
10299 texture_t *texture;
10300 const msurface_t *surface;
10301 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10303 // if the model is static it doesn't matter what value we give for
10304 // wantnormals and wanttangents, so this logic uses only rules applicable
10305 // to a model, knowing that they are meaningless otherwise
10306 if (ent == r_refdef.scene.worldentity)
10307 RSurf_ActiveWorldEntity();
10308 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10309 RSurf_ActiveModelEntity(ent, false, false, false);
10312 switch (vid.renderpath)
10314 case RENDERPATH_GL20:
10315 case RENDERPATH_D3D9:
10316 case RENDERPATH_D3D10:
10317 case RENDERPATH_D3D11:
10318 case RENDERPATH_SOFT:
10319 case RENDERPATH_GLES2:
10320 RSurf_ActiveModelEntity(ent, true, true, false);
10322 case RENDERPATH_GL11:
10323 case RENDERPATH_GL13:
10324 case RENDERPATH_GLES1:
10325 RSurf_ActiveModelEntity(ent, true, false, false);
10330 if (r_transparentdepthmasking.integer)
10332 qboolean setup = false;
10333 for (i = 0;i < numsurfaces;i = j)
10336 surface = rsurface.modelsurfaces + surfacelist[i];
10337 texture = surface->texture;
10338 rsurface.texture = R_GetCurrentTexture(texture);
10339 rsurface.lightmaptexture = NULL;
10340 rsurface.deluxemaptexture = NULL;
10341 rsurface.uselightmaptexture = false;
10342 // scan ahead until we find a different texture
10343 endsurface = min(i + 1024, numsurfaces);
10344 texturenumsurfaces = 0;
10345 texturesurfacelist[texturenumsurfaces++] = surface;
10346 for (;j < endsurface;j++)
10348 surface = rsurface.modelsurfaces + surfacelist[j];
10349 if (texture != surface->texture)
10351 texturesurfacelist[texturenumsurfaces++] = surface;
10353 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10355 // render the range of surfaces as depth
10359 GL_ColorMask(0,0,0,0);
10361 GL_DepthTest(true);
10362 GL_BlendFunc(GL_ONE, GL_ZERO);
10363 GL_DepthMask(true);
10364 // R_Mesh_ResetTextureState();
10365 R_SetupShader_DepthOrShadow(false);
10367 RSurf_SetupDepthAndCulling();
10368 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10369 if (rsurface.batchvertex3fbuffer)
10370 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10372 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10376 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10379 for (i = 0;i < numsurfaces;i = j)
10382 surface = rsurface.modelsurfaces + surfacelist[i];
10383 texture = surface->texture;
10384 rsurface.texture = R_GetCurrentTexture(texture);
10385 // scan ahead until we find a different texture
10386 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10387 texturenumsurfaces = 0;
10388 texturesurfacelist[texturenumsurfaces++] = surface;
10389 if(FAKELIGHT_ENABLED)
10391 rsurface.lightmaptexture = NULL;
10392 rsurface.deluxemaptexture = NULL;
10393 rsurface.uselightmaptexture = false;
10394 for (;j < endsurface;j++)
10396 surface = rsurface.modelsurfaces + surfacelist[j];
10397 if (texture != surface->texture)
10399 texturesurfacelist[texturenumsurfaces++] = surface;
10404 rsurface.lightmaptexture = surface->lightmaptexture;
10405 rsurface.deluxemaptexture = surface->deluxemaptexture;
10406 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10407 for (;j < endsurface;j++)
10409 surface = rsurface.modelsurfaces + surfacelist[j];
10410 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10412 texturesurfacelist[texturenumsurfaces++] = surface;
10415 // render the range of surfaces
10416 if (ent == r_refdef.scene.worldentity)
10417 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10419 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10421 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10424 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10426 // transparent surfaces get pushed off into the transparent queue
10427 int surfacelistindex;
10428 const msurface_t *surface;
10429 vec3_t tempcenter, center;
10430 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10432 surface = texturesurfacelist[surfacelistindex];
10433 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10434 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10435 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10436 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10437 if (queueentity->transparent_offset) // transparent offset
10439 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10440 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10441 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10443 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10447 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10449 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10451 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10453 RSurf_SetupDepthAndCulling();
10454 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10455 if (rsurface.batchvertex3fbuffer)
10456 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10458 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10462 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10464 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10467 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10470 if (!rsurface.texture->currentnumlayers)
10472 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10473 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10475 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10477 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10478 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10479 else if (!rsurface.texture->currentnumlayers)
10481 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10483 // in the deferred case, transparent surfaces were queued during prepass
10484 if (!r_shadow_usingdeferredprepass)
10485 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10489 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10490 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10495 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10498 texture_t *texture;
10499 R_FrameData_SetMark();
10500 // break the surface list down into batches by texture and use of lightmapping
10501 for (i = 0;i < numsurfaces;i = j)
10504 // texture is the base texture pointer, rsurface.texture is the
10505 // current frame/skin the texture is directing us to use (for example
10506 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10507 // use skin 1 instead)
10508 texture = surfacelist[i]->texture;
10509 rsurface.texture = R_GetCurrentTexture(texture);
10510 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10512 // if this texture is not the kind we want, skip ahead to the next one
10513 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10517 if(FAKELIGHT_ENABLED || depthonly || prepass)
10519 rsurface.lightmaptexture = NULL;
10520 rsurface.deluxemaptexture = NULL;
10521 rsurface.uselightmaptexture = false;
10522 // simply scan ahead until we find a different texture or lightmap state
10523 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10528 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10529 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10530 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10531 // simply scan ahead until we find a different texture or lightmap state
10532 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10535 // render the range of surfaces
10536 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10538 R_FrameData_ReturnToMark();
10541 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10545 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10548 if (!rsurface.texture->currentnumlayers)
10550 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10551 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10553 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10555 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10556 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10557 else if (!rsurface.texture->currentnumlayers)
10559 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10561 // in the deferred case, transparent surfaces were queued during prepass
10562 if (!r_shadow_usingdeferredprepass)
10563 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10567 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10568 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10573 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10576 texture_t *texture;
10577 R_FrameData_SetMark();
10578 // break the surface list down into batches by texture and use of lightmapping
10579 for (i = 0;i < numsurfaces;i = j)
10582 // texture is the base texture pointer, rsurface.texture is the
10583 // current frame/skin the texture is directing us to use (for example
10584 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10585 // use skin 1 instead)
10586 texture = surfacelist[i]->texture;
10587 rsurface.texture = R_GetCurrentTexture(texture);
10588 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10590 // if this texture is not the kind we want, skip ahead to the next one
10591 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10595 if(FAKELIGHT_ENABLED || depthonly || prepass)
10597 rsurface.lightmaptexture = NULL;
10598 rsurface.deluxemaptexture = NULL;
10599 rsurface.uselightmaptexture = false;
10600 // simply scan ahead until we find a different texture or lightmap state
10601 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10606 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10607 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10608 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10609 // simply scan ahead until we find a different texture or lightmap state
10610 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10613 // render the range of surfaces
10614 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10616 R_FrameData_ReturnToMark();
10619 float locboxvertex3f[6*4*3] =
10621 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10622 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10623 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10624 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10625 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10626 1,0,0, 0,0,0, 0,1,0, 1,1,0
10629 unsigned short locboxelements[6*2*3] =
10634 12,13,14, 12,14,15,
10635 16,17,18, 16,18,19,
10639 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10642 cl_locnode_t *loc = (cl_locnode_t *)ent;
10644 float vertex3f[6*4*3];
10646 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10647 GL_DepthMask(false);
10648 GL_DepthRange(0, 1);
10649 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10650 GL_DepthTest(true);
10651 GL_CullFace(GL_NONE);
10652 R_EntityMatrix(&identitymatrix);
10654 // R_Mesh_ResetTextureState();
10656 i = surfacelist[0];
10657 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10658 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10659 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10660 surfacelist[0] < 0 ? 0.5f : 0.125f);
10662 if (VectorCompare(loc->mins, loc->maxs))
10664 VectorSet(size, 2, 2, 2);
10665 VectorMA(loc->mins, -0.5f, size, mins);
10669 VectorCopy(loc->mins, mins);
10670 VectorSubtract(loc->maxs, loc->mins, size);
10673 for (i = 0;i < 6*4*3;)
10674 for (j = 0;j < 3;j++, i++)
10675 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10677 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10678 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10679 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10682 void R_DrawLocs(void)
10685 cl_locnode_t *loc, *nearestloc;
10687 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10688 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10690 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10691 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10695 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10697 if (decalsystem->decals)
10698 Mem_Free(decalsystem->decals);
10699 memset(decalsystem, 0, sizeof(*decalsystem));
10702 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, int decalsequence)
10705 tridecal_t *decals;
10708 // expand or initialize the system
10709 if (decalsystem->maxdecals <= decalsystem->numdecals)
10711 decalsystem_t old = *decalsystem;
10712 qboolean useshortelements;
10713 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10714 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10715 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)));
10716 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10717 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10718 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10719 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10720 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10721 if (decalsystem->numdecals)
10722 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10724 Mem_Free(old.decals);
10725 for (i = 0;i < decalsystem->maxdecals*3;i++)
10726 decalsystem->element3i[i] = i;
10727 if (useshortelements)
10728 for (i = 0;i < decalsystem->maxdecals*3;i++)
10729 decalsystem->element3s[i] = i;
10732 // grab a decal and search for another free slot for the next one
10733 decals = decalsystem->decals;
10734 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10735 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10737 decalsystem->freedecal = i;
10738 if (decalsystem->numdecals <= i)
10739 decalsystem->numdecals = i + 1;
10741 // initialize the decal
10743 decal->triangleindex = triangleindex;
10744 decal->surfaceindex = surfaceindex;
10745 decal->decalsequence = decalsequence;
10746 decal->color4f[0][0] = c0[0];
10747 decal->color4f[0][1] = c0[1];
10748 decal->color4f[0][2] = c0[2];
10749 decal->color4f[0][3] = 1;
10750 decal->color4f[1][0] = c1[0];
10751 decal->color4f[1][1] = c1[1];
10752 decal->color4f[1][2] = c1[2];
10753 decal->color4f[1][3] = 1;
10754 decal->color4f[2][0] = c2[0];
10755 decal->color4f[2][1] = c2[1];
10756 decal->color4f[2][2] = c2[2];
10757 decal->color4f[2][3] = 1;
10758 decal->vertex3f[0][0] = v0[0];
10759 decal->vertex3f[0][1] = v0[1];
10760 decal->vertex3f[0][2] = v0[2];
10761 decal->vertex3f[1][0] = v1[0];
10762 decal->vertex3f[1][1] = v1[1];
10763 decal->vertex3f[1][2] = v1[2];
10764 decal->vertex3f[2][0] = v2[0];
10765 decal->vertex3f[2][1] = v2[1];
10766 decal->vertex3f[2][2] = v2[2];
10767 decal->texcoord2f[0][0] = t0[0];
10768 decal->texcoord2f[0][1] = t0[1];
10769 decal->texcoord2f[1][0] = t1[0];
10770 decal->texcoord2f[1][1] = t1[1];
10771 decal->texcoord2f[2][0] = t2[0];
10772 decal->texcoord2f[2][1] = t2[1];
10773 TriangleNormal(v0, v1, v2, decal->plane);
10774 VectorNormalize(decal->plane);
10775 decal->plane[3] = DotProduct(v0, decal->plane);
10778 extern cvar_t cl_decals_bias;
10779 extern cvar_t cl_decals_models;
10780 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10781 // baseparms, parms, temps
10782 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
10787 const float *vertex3f;
10788 const float *normal3f;
10790 float points[2][9][3];
10797 e = rsurface.modelelement3i + 3*triangleindex;
10799 vertex3f = rsurface.modelvertex3f;
10800 normal3f = rsurface.modelnormal3f;
10804 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10806 index = 3*e[cornerindex];
10807 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10812 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10814 index = 3*e[cornerindex];
10815 VectorCopy(vertex3f + index, v[cornerindex]);
10820 //TriangleNormal(v[0], v[1], v[2], normal);
10821 //if (DotProduct(normal, localnormal) < 0.0f)
10823 // clip by each of the box planes formed from the projection matrix
10824 // if anything survives, we emit the decal
10825 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]);
10828 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]);
10831 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]);
10834 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]);
10837 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]);
10840 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]);
10843 // some part of the triangle survived, so we have to accept it...
10846 // dynamic always uses the original triangle
10848 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10850 index = 3*e[cornerindex];
10851 VectorCopy(vertex3f + index, v[cornerindex]);
10854 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10856 // convert vertex positions to texcoords
10857 Matrix4x4_Transform(projection, v[cornerindex], temp);
10858 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10859 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10860 // calculate distance fade from the projection origin
10861 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10862 f = bound(0.0f, f, 1.0f);
10863 c[cornerindex][0] = r * f;
10864 c[cornerindex][1] = g * f;
10865 c[cornerindex][2] = b * f;
10866 c[cornerindex][3] = 1.0f;
10867 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10870 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);
10872 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10873 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);
10875 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, int decalsequence)
10877 matrix4x4_t projection;
10878 decalsystem_t *decalsystem;
10881 const msurface_t *surface;
10882 const msurface_t *surfaces;
10883 const int *surfacelist;
10884 const texture_t *texture;
10886 int numsurfacelist;
10887 int surfacelistindex;
10890 float localorigin[3];
10891 float localnormal[3];
10892 float localmins[3];
10893 float localmaxs[3];
10896 float planes[6][4];
10899 int bih_triangles_count;
10900 int bih_triangles[256];
10901 int bih_surfaces[256];
10903 decalsystem = &ent->decalsystem;
10904 model = ent->model;
10905 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10907 R_DecalSystem_Reset(&ent->decalsystem);
10911 if (!model->brush.data_leafs && !cl_decals_models.integer)
10913 if (decalsystem->model)
10914 R_DecalSystem_Reset(decalsystem);
10918 if (decalsystem->model != model)
10919 R_DecalSystem_Reset(decalsystem);
10920 decalsystem->model = model;
10922 RSurf_ActiveModelEntity(ent, true, false, false);
10924 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10925 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10926 VectorNormalize(localnormal);
10927 localsize = worldsize*rsurface.inversematrixscale;
10928 localmins[0] = localorigin[0] - localsize;
10929 localmins[1] = localorigin[1] - localsize;
10930 localmins[2] = localorigin[2] - localsize;
10931 localmaxs[0] = localorigin[0] + localsize;
10932 localmaxs[1] = localorigin[1] + localsize;
10933 localmaxs[2] = localorigin[2] + localsize;
10935 //VectorCopy(localnormal, planes[4]);
10936 //VectorVectors(planes[4], planes[2], planes[0]);
10937 AnglesFromVectors(angles, localnormal, NULL, false);
10938 AngleVectors(angles, planes[0], planes[2], planes[4]);
10939 VectorNegate(planes[0], planes[1]);
10940 VectorNegate(planes[2], planes[3]);
10941 VectorNegate(planes[4], planes[5]);
10942 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10943 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10944 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10945 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10946 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10947 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10952 matrix4x4_t forwardprojection;
10953 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10954 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10959 float projectionvector[4][3];
10960 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10961 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10962 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10963 projectionvector[0][0] = planes[0][0] * ilocalsize;
10964 projectionvector[0][1] = planes[1][0] * ilocalsize;
10965 projectionvector[0][2] = planes[2][0] * ilocalsize;
10966 projectionvector[1][0] = planes[0][1] * ilocalsize;
10967 projectionvector[1][1] = planes[1][1] * ilocalsize;
10968 projectionvector[1][2] = planes[2][1] * ilocalsize;
10969 projectionvector[2][0] = planes[0][2] * ilocalsize;
10970 projectionvector[2][1] = planes[1][2] * ilocalsize;
10971 projectionvector[2][2] = planes[2][2] * ilocalsize;
10972 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10973 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10974 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10975 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10979 dynamic = model->surfmesh.isanimated;
10980 numsurfacelist = model->nummodelsurfaces;
10981 surfacelist = model->sortedmodelsurfaces;
10982 surfaces = model->data_surfaces;
10985 bih_triangles_count = -1;
10988 if(model->render_bih.numleafs)
10989 bih = &model->render_bih;
10990 else if(model->collision_bih.numleafs)
10991 bih = &model->collision_bih;
10994 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10995 if(bih_triangles_count == 0)
10997 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10999 if(bih_triangles_count > 0)
11001 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11003 surfaceindex = bih_surfaces[triangleindex];
11004 surface = surfaces + surfaceindex;
11005 texture = surface->texture;
11006 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11008 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11010 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11015 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11017 surfaceindex = surfacelist[surfacelistindex];
11018 surface = surfaces + surfaceindex;
11019 // check cull box first because it rejects more than any other check
11020 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11022 // skip transparent surfaces
11023 texture = surface->texture;
11024 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11026 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11028 numtriangles = surface->num_triangles;
11029 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11030 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11035 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11036 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, int decalsequence)
11038 int renderentityindex;
11039 float worldmins[3];
11040 float worldmaxs[3];
11041 entity_render_t *ent;
11043 if (!cl_decals_newsystem.integer)
11046 worldmins[0] = worldorigin[0] - worldsize;
11047 worldmins[1] = worldorigin[1] - worldsize;
11048 worldmins[2] = worldorigin[2] - worldsize;
11049 worldmaxs[0] = worldorigin[0] + worldsize;
11050 worldmaxs[1] = worldorigin[1] + worldsize;
11051 worldmaxs[2] = worldorigin[2] + worldsize;
11053 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11055 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11057 ent = r_refdef.scene.entities[renderentityindex];
11058 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11061 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11065 typedef struct r_decalsystem_splatqueue_s
11067 vec3_t worldorigin;
11068 vec3_t worldnormal;
11074 r_decalsystem_splatqueue_t;
11076 int r_decalsystem_numqueued = 0;
11077 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11079 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)
11081 r_decalsystem_splatqueue_t *queue;
11083 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11086 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11087 VectorCopy(worldorigin, queue->worldorigin);
11088 VectorCopy(worldnormal, queue->worldnormal);
11089 Vector4Set(queue->color, r, g, b, a);
11090 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11091 queue->worldsize = worldsize;
11092 queue->decalsequence = cl.decalsequence++;
11095 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11098 r_decalsystem_splatqueue_t *queue;
11100 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11101 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);
11102 r_decalsystem_numqueued = 0;
11105 extern cvar_t cl_decals_max;
11106 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11109 decalsystem_t *decalsystem = &ent->decalsystem;
11116 if (!decalsystem->numdecals)
11119 if (r_showsurfaces.integer)
11122 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11124 R_DecalSystem_Reset(decalsystem);
11128 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11129 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11131 if (decalsystem->lastupdatetime)
11132 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11135 decalsystem->lastupdatetime = r_refdef.scene.time;
11136 decal = decalsystem->decals;
11137 numdecals = decalsystem->numdecals;
11139 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11141 if (decal->color4f[0][3])
11143 decal->lived += frametime;
11144 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11146 memset(decal, 0, sizeof(*decal));
11147 if (decalsystem->freedecal > i)
11148 decalsystem->freedecal = i;
11152 decal = decalsystem->decals;
11153 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11156 // collapse the array by shuffling the tail decals into the gaps
11159 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11160 decalsystem->freedecal++;
11161 if (decalsystem->freedecal == numdecals)
11163 decal[decalsystem->freedecal] = decal[--numdecals];
11166 decalsystem->numdecals = numdecals;
11168 if (numdecals <= 0)
11170 // if there are no decals left, reset decalsystem
11171 R_DecalSystem_Reset(decalsystem);
11175 extern skinframe_t *decalskinframe;
11176 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11179 decalsystem_t *decalsystem = &ent->decalsystem;
11188 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11191 numdecals = decalsystem->numdecals;
11195 if (r_showsurfaces.integer)
11198 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11200 R_DecalSystem_Reset(decalsystem);
11204 // if the model is static it doesn't matter what value we give for
11205 // wantnormals and wanttangents, so this logic uses only rules applicable
11206 // to a model, knowing that they are meaningless otherwise
11207 if (ent == r_refdef.scene.worldentity)
11208 RSurf_ActiveWorldEntity();
11210 RSurf_ActiveModelEntity(ent, false, false, false);
11212 decalsystem->lastupdatetime = r_refdef.scene.time;
11213 decal = decalsystem->decals;
11215 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11217 // update vertex positions for animated models
11218 v3f = decalsystem->vertex3f;
11219 c4f = decalsystem->color4f;
11220 t2f = decalsystem->texcoord2f;
11221 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11223 if (!decal->color4f[0][3])
11226 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11230 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11233 // update color values for fading decals
11234 if (decal->lived >= cl_decals_time.value)
11235 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11239 c4f[ 0] = decal->color4f[0][0] * alpha;
11240 c4f[ 1] = decal->color4f[0][1] * alpha;
11241 c4f[ 2] = decal->color4f[0][2] * alpha;
11243 c4f[ 4] = decal->color4f[1][0] * alpha;
11244 c4f[ 5] = decal->color4f[1][1] * alpha;
11245 c4f[ 6] = decal->color4f[1][2] * alpha;
11247 c4f[ 8] = decal->color4f[2][0] * alpha;
11248 c4f[ 9] = decal->color4f[2][1] * alpha;
11249 c4f[10] = decal->color4f[2][2] * alpha;
11252 t2f[0] = decal->texcoord2f[0][0];
11253 t2f[1] = decal->texcoord2f[0][1];
11254 t2f[2] = decal->texcoord2f[1][0];
11255 t2f[3] = decal->texcoord2f[1][1];
11256 t2f[4] = decal->texcoord2f[2][0];
11257 t2f[5] = decal->texcoord2f[2][1];
11259 // update vertex positions for animated models
11260 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11262 e = rsurface.modelelement3i + 3*decal->triangleindex;
11263 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11264 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11265 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11269 VectorCopy(decal->vertex3f[0], v3f);
11270 VectorCopy(decal->vertex3f[1], v3f + 3);
11271 VectorCopy(decal->vertex3f[2], v3f + 6);
11274 if (r_refdef.fogenabled)
11276 alpha = RSurf_FogVertex(v3f);
11277 VectorScale(c4f, alpha, c4f);
11278 alpha = RSurf_FogVertex(v3f + 3);
11279 VectorScale(c4f + 4, alpha, c4f + 4);
11280 alpha = RSurf_FogVertex(v3f + 6);
11281 VectorScale(c4f + 8, alpha, c4f + 8);
11292 r_refdef.stats.drawndecals += numtris;
11294 // now render the decals all at once
11295 // (this assumes they all use one particle font texture!)
11296 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);
11297 // R_Mesh_ResetTextureState();
11298 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11299 GL_DepthMask(false);
11300 GL_DepthRange(0, 1);
11301 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11302 GL_DepthTest(true);
11303 GL_CullFace(GL_NONE);
11304 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11305 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11306 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11310 static void R_DrawModelDecals(void)
11314 // fade faster when there are too many decals
11315 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11316 for (i = 0;i < r_refdef.scene.numentities;i++)
11317 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11319 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11320 for (i = 0;i < r_refdef.scene.numentities;i++)
11321 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11322 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11324 R_DecalSystem_ApplySplatEntitiesQueue();
11326 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11327 for (i = 0;i < r_refdef.scene.numentities;i++)
11328 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11330 r_refdef.stats.totaldecals += numdecals;
11332 if (r_showsurfaces.integer)
11335 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11337 for (i = 0;i < r_refdef.scene.numentities;i++)
11339 if (!r_refdef.viewcache.entityvisible[i])
11341 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11342 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11346 extern cvar_t mod_collision_bih;
11347 void R_DrawDebugModel(void)
11349 entity_render_t *ent = rsurface.entity;
11350 int i, j, k, l, flagsmask;
11351 const msurface_t *surface;
11352 dp_model_t *model = ent->model;
11355 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11358 if (r_showoverdraw.value > 0)
11360 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11361 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11362 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11363 GL_DepthTest(false);
11364 GL_DepthMask(false);
11365 GL_DepthRange(0, 1);
11366 GL_BlendFunc(GL_ONE, GL_ONE);
11367 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11369 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11371 rsurface.texture = R_GetCurrentTexture(surface->texture);
11372 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11374 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11375 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11376 if (!rsurface.texture->currentlayers->depthmask)
11377 GL_Color(c, 0, 0, 1.0f);
11378 else if (ent == r_refdef.scene.worldentity)
11379 GL_Color(c, c, c, 1.0f);
11381 GL_Color(0, c, 0, 1.0f);
11382 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11386 rsurface.texture = NULL;
11389 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11391 // R_Mesh_ResetTextureState();
11392 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11393 GL_DepthRange(0, 1);
11394 GL_DepthTest(!r_showdisabledepthtest.integer);
11395 GL_DepthMask(false);
11396 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11398 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11402 qboolean cullbox = ent == r_refdef.scene.worldentity;
11403 const q3mbrush_t *brush;
11404 const bih_t *bih = &model->collision_bih;
11405 const bih_leaf_t *bihleaf;
11406 float vertex3f[3][3];
11407 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11409 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11411 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11413 switch (bihleaf->type)
11416 brush = model->brush.data_brushes + bihleaf->itemindex;
11417 if (brush->colbrushf && brush->colbrushf->numtriangles)
11419 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);
11420 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11421 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11424 case BIH_COLLISIONTRIANGLE:
11425 triangleindex = bihleaf->itemindex;
11426 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11427 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11428 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11429 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);
11430 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11431 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11433 case BIH_RENDERTRIANGLE:
11434 triangleindex = bihleaf->itemindex;
11435 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11436 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11437 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11438 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);
11439 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11440 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11446 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11449 if (r_showtris.integer && qglPolygonMode)
11451 if (r_showdisabledepthtest.integer)
11453 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11454 GL_DepthMask(false);
11458 GL_BlendFunc(GL_ONE, GL_ZERO);
11459 GL_DepthMask(true);
11461 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11462 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11464 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11466 rsurface.texture = R_GetCurrentTexture(surface->texture);
11467 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11469 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11470 if (!rsurface.texture->currentlayers->depthmask)
11471 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11472 else if (ent == r_refdef.scene.worldentity)
11473 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11475 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11476 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11480 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11481 rsurface.texture = NULL;
11484 if (r_shownormals.value != 0 && qglBegin)
11486 if (r_showdisabledepthtest.integer)
11488 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11489 GL_DepthMask(false);
11493 GL_BlendFunc(GL_ONE, GL_ZERO);
11494 GL_DepthMask(true);
11496 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11498 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11500 rsurface.texture = R_GetCurrentTexture(surface->texture);
11501 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11503 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11504 qglBegin(GL_LINES);
11505 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11507 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11509 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11510 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11511 qglVertex3f(v[0], v[1], v[2]);
11512 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11513 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11514 qglVertex3f(v[0], v[1], v[2]);
11517 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11519 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11521 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11522 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11523 qglVertex3f(v[0], v[1], v[2]);
11524 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11525 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11526 qglVertex3f(v[0], v[1], v[2]);
11529 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11531 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11533 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11534 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11535 qglVertex3f(v[0], v[1], v[2]);
11536 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11537 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11538 qglVertex3f(v[0], v[1], v[2]);
11541 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11543 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11545 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11546 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11547 qglVertex3f(v[0], v[1], v[2]);
11548 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11549 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11550 qglVertex3f(v[0], v[1], v[2]);
11557 rsurface.texture = NULL;
11562 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11563 int r_maxsurfacelist = 0;
11564 const msurface_t **r_surfacelist = NULL;
11565 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11567 int i, j, endj, flagsmask;
11568 dp_model_t *model = r_refdef.scene.worldmodel;
11569 msurface_t *surfaces;
11570 unsigned char *update;
11571 int numsurfacelist = 0;
11575 if (r_maxsurfacelist < model->num_surfaces)
11577 r_maxsurfacelist = model->num_surfaces;
11579 Mem_Free((msurface_t**)r_surfacelist);
11580 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11583 RSurf_ActiveWorldEntity();
11585 surfaces = model->data_surfaces;
11586 update = model->brushq1.lightmapupdateflags;
11588 // update light styles on this submodel
11589 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11591 model_brush_lightstyleinfo_t *style;
11592 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11594 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11596 int *list = style->surfacelist;
11597 style->value = r_refdef.scene.lightstylevalue[style->style];
11598 for (j = 0;j < style->numsurfaces;j++)
11599 update[list[j]] = true;
11604 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11608 R_DrawDebugModel();
11609 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11613 rsurface.lightmaptexture = NULL;
11614 rsurface.deluxemaptexture = NULL;
11615 rsurface.uselightmaptexture = false;
11616 rsurface.texture = NULL;
11617 rsurface.rtlight = NULL;
11618 numsurfacelist = 0;
11619 // add visible surfaces to draw list
11620 for (i = 0;i < model->nummodelsurfaces;i++)
11622 j = model->sortedmodelsurfaces[i];
11623 if (r_refdef.viewcache.world_surfacevisible[j])
11624 r_surfacelist[numsurfacelist++] = surfaces + j;
11626 // update lightmaps if needed
11627 if (model->brushq1.firstrender)
11629 model->brushq1.firstrender = false;
11630 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11632 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11636 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11637 if (r_refdef.viewcache.world_surfacevisible[j])
11639 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11641 // don't do anything if there were no surfaces
11642 if (!numsurfacelist)
11644 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11647 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11649 // add to stats if desired
11650 if (r_speeds.integer && !skysurfaces && !depthonly)
11652 r_refdef.stats.world_surfaces += numsurfacelist;
11653 for (j = 0;j < numsurfacelist;j++)
11654 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11657 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11660 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11662 int i, j, endj, flagsmask;
11663 dp_model_t *model = ent->model;
11664 msurface_t *surfaces;
11665 unsigned char *update;
11666 int numsurfacelist = 0;
11670 if (r_maxsurfacelist < model->num_surfaces)
11672 r_maxsurfacelist = model->num_surfaces;
11674 Mem_Free((msurface_t **)r_surfacelist);
11675 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11678 // if the model is static it doesn't matter what value we give for
11679 // wantnormals and wanttangents, so this logic uses only rules applicable
11680 // to a model, knowing that they are meaningless otherwise
11681 if (ent == r_refdef.scene.worldentity)
11682 RSurf_ActiveWorldEntity();
11683 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11684 RSurf_ActiveModelEntity(ent, false, false, false);
11686 RSurf_ActiveModelEntity(ent, true, true, true);
11687 else if (depthonly)
11689 switch (vid.renderpath)
11691 case RENDERPATH_GL20:
11692 case RENDERPATH_D3D9:
11693 case RENDERPATH_D3D10:
11694 case RENDERPATH_D3D11:
11695 case RENDERPATH_SOFT:
11696 case RENDERPATH_GLES2:
11697 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11699 case RENDERPATH_GL11:
11700 case RENDERPATH_GL13:
11701 case RENDERPATH_GLES1:
11702 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11708 switch (vid.renderpath)
11710 case RENDERPATH_GL20:
11711 case RENDERPATH_D3D9:
11712 case RENDERPATH_D3D10:
11713 case RENDERPATH_D3D11:
11714 case RENDERPATH_SOFT:
11715 case RENDERPATH_GLES2:
11716 RSurf_ActiveModelEntity(ent, true, true, false);
11718 case RENDERPATH_GL11:
11719 case RENDERPATH_GL13:
11720 case RENDERPATH_GLES1:
11721 RSurf_ActiveModelEntity(ent, true, false, false);
11726 surfaces = model->data_surfaces;
11727 update = model->brushq1.lightmapupdateflags;
11729 // update light styles
11730 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11732 model_brush_lightstyleinfo_t *style;
11733 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11735 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11737 int *list = style->surfacelist;
11738 style->value = r_refdef.scene.lightstylevalue[style->style];
11739 for (j = 0;j < style->numsurfaces;j++)
11740 update[list[j]] = true;
11745 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11749 R_DrawDebugModel();
11750 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11754 rsurface.lightmaptexture = NULL;
11755 rsurface.deluxemaptexture = NULL;
11756 rsurface.uselightmaptexture = false;
11757 rsurface.texture = NULL;
11758 rsurface.rtlight = NULL;
11759 numsurfacelist = 0;
11760 // add visible surfaces to draw list
11761 for (i = 0;i < model->nummodelsurfaces;i++)
11762 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11763 // don't do anything if there were no surfaces
11764 if (!numsurfacelist)
11766 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11769 // update lightmaps if needed
11773 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11778 R_BuildLightMap(ent, surfaces + j);
11783 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11785 R_BuildLightMap(ent, surfaces + j);
11786 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11788 // add to stats if desired
11789 if (r_speeds.integer && !skysurfaces && !depthonly)
11791 r_refdef.stats.entities_surfaces += numsurfacelist;
11792 for (j = 0;j < numsurfacelist;j++)
11793 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11796 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11799 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11801 static texture_t texture;
11802 static msurface_t surface;
11803 const msurface_t *surfacelist = &surface;
11805 // fake enough texture and surface state to render this geometry
11807 texture.update_lastrenderframe = -1; // regenerate this texture
11808 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11809 texture.currentskinframe = skinframe;
11810 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11811 texture.offsetmapping = OFFSETMAPPING_OFF;
11812 texture.offsetscale = 1;
11813 texture.specularscalemod = 1;
11814 texture.specularpowermod = 1;
11816 surface.texture = &texture;
11817 surface.num_triangles = numtriangles;
11818 surface.num_firsttriangle = firsttriangle;
11819 surface.num_vertices = numvertices;
11820 surface.num_firstvertex = firstvertex;
11823 rsurface.texture = R_GetCurrentTexture(surface.texture);
11824 rsurface.lightmaptexture = NULL;
11825 rsurface.deluxemaptexture = NULL;
11826 rsurface.uselightmaptexture = false;
11827 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11830 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)
11832 static msurface_t surface;
11833 const msurface_t *surfacelist = &surface;
11835 // fake enough texture and surface state to render this geometry
11836 surface.texture = texture;
11837 surface.num_triangles = numtriangles;
11838 surface.num_firsttriangle = firsttriangle;
11839 surface.num_vertices = numvertices;
11840 surface.num_firstvertex = firstvertex;
11843 rsurface.texture = R_GetCurrentTexture(surface.texture);
11844 rsurface.lightmaptexture = NULL;
11845 rsurface.deluxemaptexture = NULL;
11846 rsurface.uselightmaptexture = false;
11847 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);