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;
830 int loc_OffsetMapping_Bias;
832 int loc_ReflectColor;
833 int loc_ReflectFactor;
834 int loc_ReflectOffset;
835 int loc_RefractColor;
837 int loc_ScreenCenterRefractReflect;
838 int loc_ScreenScaleRefractReflect;
839 int loc_ScreenToDepth;
840 int loc_ShadowMap_Parameters;
841 int loc_ShadowMap_TextureScale;
842 int loc_SpecularPower;
847 int loc_ViewTintColor;
849 int loc_ModelToLight;
851 int loc_BackgroundTexMatrix;
852 int loc_ModelViewProjectionMatrix;
853 int loc_ModelViewMatrix;
854 int loc_PixelToScreenTexCoord;
855 int loc_ModelToReflectCube;
856 int loc_ShadowMapMatrix;
857 int loc_BloomColorSubtract;
858 int loc_NormalmapScrollBlend;
859 int loc_BounceGridMatrix;
860 int loc_BounceGridIntensity;
862 r_glsl_permutation_t;
864 #define SHADERPERMUTATION_HASHSIZE 256
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
871 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
877 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
880 #define SHADERSTATICPARMS_COUNT 8
882 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
883 static int shaderstaticparms_count = 0;
885 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
886 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
887 qboolean R_CompileShader_CheckStaticParms(void)
889 static int r_compileshader_staticparms_save[1];
890 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
891 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
894 if (r_glsl_saturation_redcompensate.integer)
895 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
896 if (r_glsl_vertextextureblend_usebothalphas.integer)
897 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
898 if (r_shadow_glossexact.integer)
899 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
900 if (r_glsl_postprocess.integer)
902 if (r_glsl_postprocess_uservec1_enable.integer)
903 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
904 if (r_glsl_postprocess_uservec2_enable.integer)
905 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
906 if (r_glsl_postprocess_uservec3_enable.integer)
907 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
908 if (r_glsl_postprocess_uservec4_enable.integer)
909 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
911 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
912 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
913 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
916 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
917 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
918 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
920 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
921 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
923 shaderstaticparms_count = 0;
926 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
927 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
928 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
929 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
930 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
931 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
932 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
933 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
936 /// information about each possible shader permutation
937 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
938 /// currently selected permutation
939 r_glsl_permutation_t *r_glsl_permutation;
940 /// storage for permutations linked in the hash table
941 memexpandablearray_t r_glsl_permutationarray;
943 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
945 //unsigned int hashdepth = 0;
946 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
947 r_glsl_permutation_t *p;
948 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
950 if (p->mode == mode && p->permutation == permutation)
952 //if (hashdepth > 10)
953 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
958 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
960 p->permutation = permutation;
961 p->hashnext = r_glsl_permutationhash[mode][hashindex];
962 r_glsl_permutationhash[mode][hashindex] = p;
963 //if (hashdepth > 10)
964 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
968 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
971 if (!filename || !filename[0])
973 if (!strcmp(filename, "glsl/default.glsl"))
975 if (!glslshaderstring)
977 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
978 if (glslshaderstring)
979 Con_DPrintf("Loading shaders from file %s...\n", filename);
981 glslshaderstring = (char *)builtinshaderstring;
983 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
984 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
987 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
990 if (printfromdisknotice)
991 Con_DPrintf("from disk %s... ", filename);
997 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1001 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1002 char *vertexstring, *geometrystring, *fragmentstring;
1003 char permutationname[256];
1004 int vertstrings_count = 0;
1005 int geomstrings_count = 0;
1006 int fragstrings_count = 0;
1007 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1008 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1009 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1016 permutationname[0] = 0;
1017 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1018 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1019 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1021 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1023 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1024 if(vid.support.gl20shaders130)
1026 vertstrings_list[vertstrings_count++] = "#version 130\n";
1027 geomstrings_list[geomstrings_count++] = "#version 130\n";
1028 fragstrings_list[fragstrings_count++] = "#version 130\n";
1029 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1030 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1031 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1034 // the first pretext is which type of shader to compile as
1035 // (later these will all be bound together as a program object)
1036 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1037 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1038 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1040 // the second pretext is the mode (for example a light source)
1041 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1042 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1043 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1044 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1046 // now add all the permutation pretexts
1047 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1049 if (permutation & (1<<i))
1051 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1052 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1053 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1054 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1058 // keep line numbers correct
1059 vertstrings_list[vertstrings_count++] = "\n";
1060 geomstrings_list[geomstrings_count++] = "\n";
1061 fragstrings_list[fragstrings_count++] = "\n";
1066 R_CompileShader_AddStaticParms(mode, permutation);
1067 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1068 vertstrings_count += shaderstaticparms_count;
1069 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1070 geomstrings_count += shaderstaticparms_count;
1071 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1072 fragstrings_count += shaderstaticparms_count;
1074 // now append the shader text itself
1075 vertstrings_list[vertstrings_count++] = vertexstring;
1076 geomstrings_list[geomstrings_count++] = geometrystring;
1077 fragstrings_list[fragstrings_count++] = fragmentstring;
1079 // if any sources were NULL, clear the respective list
1081 vertstrings_count = 0;
1082 if (!geometrystring)
1083 geomstrings_count = 0;
1084 if (!fragmentstring)
1085 fragstrings_count = 0;
1087 // compile the shader program
1088 if (vertstrings_count + geomstrings_count + fragstrings_count)
1089 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1093 qglUseProgram(p->program);CHECKGLERROR
1094 // look up all the uniform variable names we care about, so we don't
1095 // have to look them up every time we set them
1097 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1098 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1099 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1100 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1101 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1102 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1103 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1104 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1105 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1106 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1107 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1108 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1109 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1110 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1111 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1112 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1113 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1114 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1115 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1116 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1117 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1118 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1119 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1120 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1121 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1122 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1123 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1124 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1125 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1126 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1127 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1128 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1129 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1130 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1131 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1132 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1133 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1134 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1135 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1136 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1137 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1138 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1139 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1140 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1141 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1142 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1143 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1144 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1145 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1146 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1147 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1148 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1149 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1150 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1151 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1152 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1153 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1154 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1155 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1156 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1157 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1158 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1159 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1160 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1161 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1162 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1163 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1164 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1165 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1166 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1167 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1168 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1169 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1170 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1171 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1172 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1173 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1174 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1175 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1176 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1177 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1178 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1179 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1180 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1181 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1182 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1183 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1184 // initialize the samplers to refer to the texture units we use
1185 p->tex_Texture_First = -1;
1186 p->tex_Texture_Second = -1;
1187 p->tex_Texture_GammaRamps = -1;
1188 p->tex_Texture_Normal = -1;
1189 p->tex_Texture_Color = -1;
1190 p->tex_Texture_Gloss = -1;
1191 p->tex_Texture_Glow = -1;
1192 p->tex_Texture_SecondaryNormal = -1;
1193 p->tex_Texture_SecondaryColor = -1;
1194 p->tex_Texture_SecondaryGloss = -1;
1195 p->tex_Texture_SecondaryGlow = -1;
1196 p->tex_Texture_Pants = -1;
1197 p->tex_Texture_Shirt = -1;
1198 p->tex_Texture_FogHeightTexture = -1;
1199 p->tex_Texture_FogMask = -1;
1200 p->tex_Texture_Lightmap = -1;
1201 p->tex_Texture_Deluxemap = -1;
1202 p->tex_Texture_Attenuation = -1;
1203 p->tex_Texture_Cube = -1;
1204 p->tex_Texture_Refraction = -1;
1205 p->tex_Texture_Reflection = -1;
1206 p->tex_Texture_ShadowMap2D = -1;
1207 p->tex_Texture_CubeProjection = -1;
1208 p->tex_Texture_ScreenDepth = -1;
1209 p->tex_Texture_ScreenNormalMap = -1;
1210 p->tex_Texture_ScreenDiffuse = -1;
1211 p->tex_Texture_ScreenSpecular = -1;
1212 p->tex_Texture_ReflectMask = -1;
1213 p->tex_Texture_ReflectCube = -1;
1214 p->tex_Texture_BounceGrid = -1;
1216 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1217 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1218 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1219 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1220 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1221 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1222 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1223 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1224 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1225 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1226 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1227 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1228 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1229 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1230 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1231 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1232 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1233 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1234 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1235 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1236 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1237 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1238 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1239 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1240 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1241 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1242 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1243 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1244 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1245 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1247 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1250 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1254 Mem_Free(vertexstring);
1256 Mem_Free(geometrystring);
1258 Mem_Free(fragmentstring);
1261 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1263 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1264 if (r_glsl_permutation != perm)
1266 r_glsl_permutation = perm;
1267 if (!r_glsl_permutation->program)
1269 if (!r_glsl_permutation->compiled)
1270 R_GLSL_CompilePermutation(perm, mode, permutation);
1271 if (!r_glsl_permutation->program)
1273 // remove features until we find a valid permutation
1275 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1277 // reduce i more quickly whenever it would not remove any bits
1278 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1279 if (!(permutation & j))
1282 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1283 if (!r_glsl_permutation->compiled)
1284 R_GLSL_CompilePermutation(perm, mode, permutation);
1285 if (r_glsl_permutation->program)
1288 if (i >= SHADERPERMUTATION_COUNT)
1290 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1291 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1292 qglUseProgram(0);CHECKGLERROR
1293 return; // no bit left to clear, entire mode is broken
1298 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1300 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1301 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1302 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1309 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1310 extern D3DCAPS9 vid_d3d9caps;
1313 struct r_hlsl_permutation_s;
1314 typedef struct r_hlsl_permutation_s
1316 /// hash lookup data
1317 struct r_hlsl_permutation_s *hashnext;
1319 unsigned int permutation;
1321 /// indicates if we have tried compiling this permutation already
1323 /// NULL if compilation failed
1324 IDirect3DVertexShader9 *vertexshader;
1325 IDirect3DPixelShader9 *pixelshader;
1327 r_hlsl_permutation_t;
1329 typedef enum D3DVSREGISTER_e
1331 D3DVSREGISTER_TexMatrix = 0, // float4x4
1332 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1333 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1334 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1335 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1336 D3DVSREGISTER_ModelToLight = 20, // float4x4
1337 D3DVSREGISTER_EyePosition = 24,
1338 D3DVSREGISTER_FogPlane = 25,
1339 D3DVSREGISTER_LightDir = 26,
1340 D3DVSREGISTER_LightPosition = 27,
1344 typedef enum D3DPSREGISTER_e
1346 D3DPSREGISTER_Alpha = 0,
1347 D3DPSREGISTER_BloomBlur_Parameters = 1,
1348 D3DPSREGISTER_ClientTime = 2,
1349 D3DPSREGISTER_Color_Ambient = 3,
1350 D3DPSREGISTER_Color_Diffuse = 4,
1351 D3DPSREGISTER_Color_Specular = 5,
1352 D3DPSREGISTER_Color_Glow = 6,
1353 D3DPSREGISTER_Color_Pants = 7,
1354 D3DPSREGISTER_Color_Shirt = 8,
1355 D3DPSREGISTER_DeferredColor_Ambient = 9,
1356 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1357 D3DPSREGISTER_DeferredColor_Specular = 11,
1358 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1359 D3DPSREGISTER_DeferredMod_Specular = 13,
1360 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1361 D3DPSREGISTER_EyePosition = 15, // unused
1362 D3DPSREGISTER_FogColor = 16,
1363 D3DPSREGISTER_FogHeightFade = 17,
1364 D3DPSREGISTER_FogPlane = 18,
1365 D3DPSREGISTER_FogPlaneViewDist = 19,
1366 D3DPSREGISTER_FogRangeRecip = 20,
1367 D3DPSREGISTER_LightColor = 21,
1368 D3DPSREGISTER_LightDir = 22, // unused
1369 D3DPSREGISTER_LightPosition = 23,
1370 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1371 D3DPSREGISTER_PixelSize = 25,
1372 D3DPSREGISTER_ReflectColor = 26,
1373 D3DPSREGISTER_ReflectFactor = 27,
1374 D3DPSREGISTER_ReflectOffset = 28,
1375 D3DPSREGISTER_RefractColor = 29,
1376 D3DPSREGISTER_Saturation = 30,
1377 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1378 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1379 D3DPSREGISTER_ScreenToDepth = 33,
1380 D3DPSREGISTER_ShadowMap_Parameters = 34,
1381 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1382 D3DPSREGISTER_SpecularPower = 36,
1383 D3DPSREGISTER_UserVec1 = 37,
1384 D3DPSREGISTER_UserVec2 = 38,
1385 D3DPSREGISTER_UserVec3 = 39,
1386 D3DPSREGISTER_UserVec4 = 40,
1387 D3DPSREGISTER_ViewTintColor = 41,
1388 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1389 D3DPSREGISTER_BloomColorSubtract = 43,
1390 D3DPSREGISTER_ViewToLight = 44, // float4x4
1391 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1392 D3DPSREGISTER_NormalmapScrollBlend = 52,
1393 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1394 D3DPSREGISTER_OffsetMapping_Bias = 54,
1399 /// information about each possible shader permutation
1400 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1401 /// currently selected permutation
1402 r_hlsl_permutation_t *r_hlsl_permutation;
1403 /// storage for permutations linked in the hash table
1404 memexpandablearray_t r_hlsl_permutationarray;
1406 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1408 //unsigned int hashdepth = 0;
1409 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1410 r_hlsl_permutation_t *p;
1411 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1413 if (p->mode == mode && p->permutation == permutation)
1415 //if (hashdepth > 10)
1416 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1421 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1423 p->permutation = permutation;
1424 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1425 r_hlsl_permutationhash[mode][hashindex] = p;
1426 //if (hashdepth > 10)
1427 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1431 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1434 if (!filename || !filename[0])
1436 if (!strcmp(filename, "hlsl/default.hlsl"))
1438 if (!hlslshaderstring)
1440 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1441 if (hlslshaderstring)
1442 Con_DPrintf("Loading shaders from file %s...\n", filename);
1444 hlslshaderstring = (char *)builtinhlslshaderstring;
1446 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1447 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1448 return shaderstring;
1450 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1453 if (printfromdisknotice)
1454 Con_DPrintf("from disk %s... ", filename);
1455 return shaderstring;
1457 return shaderstring;
1461 //#include <d3dx9shader.h>
1462 //#include <d3dx9mesh.h>
1464 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1466 DWORD *vsbin = NULL;
1467 DWORD *psbin = NULL;
1468 fs_offset_t vsbinsize;
1469 fs_offset_t psbinsize;
1470 // IDirect3DVertexShader9 *vs = NULL;
1471 // IDirect3DPixelShader9 *ps = NULL;
1472 ID3DXBuffer *vslog = NULL;
1473 ID3DXBuffer *vsbuffer = NULL;
1474 ID3DXConstantTable *vsconstanttable = NULL;
1475 ID3DXBuffer *pslog = NULL;
1476 ID3DXBuffer *psbuffer = NULL;
1477 ID3DXConstantTable *psconstanttable = NULL;
1480 char temp[MAX_INPUTLINE];
1481 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1482 qboolean debugshader = gl_paranoid.integer != 0;
1483 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1484 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1487 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1488 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1490 if ((!vsbin && vertstring) || (!psbin && fragstring))
1492 const char* dllnames_d3dx9 [] =
1516 dllhandle_t d3dx9_dll = NULL;
1517 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1518 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1519 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1520 dllfunction_t d3dx9_dllfuncs[] =
1522 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1523 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1524 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1527 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1529 DWORD shaderflags = 0;
1531 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1532 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1533 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1534 if (vertstring && vertstring[0])
1538 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1539 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1540 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1541 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1544 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1547 vsbinsize = vsbuffer->GetBufferSize();
1548 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1549 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1550 vsbuffer->Release();
1554 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1555 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1559 if (fragstring && fragstring[0])
1563 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1564 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1565 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1566 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1569 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1572 psbinsize = psbuffer->GetBufferSize();
1573 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1574 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1575 psbuffer->Release();
1579 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1580 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1584 Sys_UnloadLibrary(&d3dx9_dll);
1587 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1591 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1592 if (FAILED(vsresult))
1593 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1594 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1595 if (FAILED(psresult))
1596 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1598 // free the shader data
1599 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1600 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1603 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1606 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1607 int vertstring_length = 0;
1608 int geomstring_length = 0;
1609 int fragstring_length = 0;
1611 char *vertexstring, *geometrystring, *fragmentstring;
1612 char *vertstring, *geomstring, *fragstring;
1613 char permutationname[256];
1614 char cachename[256];
1615 int vertstrings_count = 0;
1616 int geomstrings_count = 0;
1617 int fragstrings_count = 0;
1618 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1619 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1620 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1625 p->vertexshader = NULL;
1626 p->pixelshader = NULL;
1628 permutationname[0] = 0;
1630 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1631 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1632 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1634 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1635 strlcat(cachename, "hlsl/", sizeof(cachename));
1637 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1638 vertstrings_count = 0;
1639 geomstrings_count = 0;
1640 fragstrings_count = 0;
1641 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1642 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1643 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1645 // the first pretext is which type of shader to compile as
1646 // (later these will all be bound together as a program object)
1647 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1648 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1649 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1651 // the second pretext is the mode (for example a light source)
1652 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1653 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1654 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1655 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1656 strlcat(cachename, modeinfo->name, sizeof(cachename));
1658 // now add all the permutation pretexts
1659 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1661 if (permutation & (1<<i))
1663 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1664 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1665 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1666 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1667 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1671 // keep line numbers correct
1672 vertstrings_list[vertstrings_count++] = "\n";
1673 geomstrings_list[geomstrings_count++] = "\n";
1674 fragstrings_list[fragstrings_count++] = "\n";
1679 R_CompileShader_AddStaticParms(mode, permutation);
1680 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1681 vertstrings_count += shaderstaticparms_count;
1682 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683 geomstrings_count += shaderstaticparms_count;
1684 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1685 fragstrings_count += shaderstaticparms_count;
1687 // replace spaces in the cachename with _ characters
1688 for (i = 0;cachename[i];i++)
1689 if (cachename[i] == ' ')
1692 // now append the shader text itself
1693 vertstrings_list[vertstrings_count++] = vertexstring;
1694 geomstrings_list[geomstrings_count++] = geometrystring;
1695 fragstrings_list[fragstrings_count++] = fragmentstring;
1697 // if any sources were NULL, clear the respective list
1699 vertstrings_count = 0;
1700 if (!geometrystring)
1701 geomstrings_count = 0;
1702 if (!fragmentstring)
1703 fragstrings_count = 0;
1705 vertstring_length = 0;
1706 for (i = 0;i < vertstrings_count;i++)
1707 vertstring_length += strlen(vertstrings_list[i]);
1708 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1709 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1710 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1712 geomstring_length = 0;
1713 for (i = 0;i < geomstrings_count;i++)
1714 geomstring_length += strlen(geomstrings_list[i]);
1715 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1716 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1717 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1719 fragstring_length = 0;
1720 for (i = 0;i < fragstrings_count;i++)
1721 fragstring_length += strlen(fragstrings_list[i]);
1722 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1723 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1724 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1726 // try to load the cached shader, or generate one
1727 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1729 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1730 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1732 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1736 Mem_Free(vertstring);
1738 Mem_Free(geomstring);
1740 Mem_Free(fragstring);
1742 Mem_Free(vertexstring);
1744 Mem_Free(geometrystring);
1746 Mem_Free(fragmentstring);
1749 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1750 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1751 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);}
1752 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);}
1753 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);}
1754 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);}
1756 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1757 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1758 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);}
1759 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);}
1760 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);}
1761 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);}
1763 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1765 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1766 if (r_hlsl_permutation != perm)
1768 r_hlsl_permutation = perm;
1769 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1771 if (!r_hlsl_permutation->compiled)
1772 R_HLSL_CompilePermutation(perm, mode, permutation);
1773 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1775 // remove features until we find a valid permutation
1777 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1779 // reduce i more quickly whenever it would not remove any bits
1780 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1781 if (!(permutation & j))
1784 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1785 if (!r_hlsl_permutation->compiled)
1786 R_HLSL_CompilePermutation(perm, mode, permutation);
1787 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1790 if (i >= SHADERPERMUTATION_COUNT)
1792 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1793 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1794 return; // no bit left to clear, entire mode is broken
1798 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1799 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1801 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1802 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1803 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1807 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1809 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1810 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1811 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1812 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1815 void R_GLSL_Restart_f(void)
1817 unsigned int i, limit;
1818 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1819 Mem_Free(glslshaderstring);
1820 glslshaderstring = NULL;
1821 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1822 Mem_Free(hlslshaderstring);
1823 hlslshaderstring = NULL;
1824 switch(vid.renderpath)
1826 case RENDERPATH_D3D9:
1829 r_hlsl_permutation_t *p;
1830 r_hlsl_permutation = NULL;
1831 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1832 for (i = 0;i < limit;i++)
1834 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1836 if (p->vertexshader)
1837 IDirect3DVertexShader9_Release(p->vertexshader);
1839 IDirect3DPixelShader9_Release(p->pixelshader);
1840 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1843 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1847 case RENDERPATH_D3D10:
1848 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1850 case RENDERPATH_D3D11:
1851 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1853 case RENDERPATH_GL20:
1854 case RENDERPATH_GLES2:
1856 r_glsl_permutation_t *p;
1857 r_glsl_permutation = NULL;
1858 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1859 for (i = 0;i < limit;i++)
1861 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1863 GL_Backend_FreeProgram(p->program);
1864 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1867 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1870 case RENDERPATH_GL11:
1871 case RENDERPATH_GL13:
1872 case RENDERPATH_GLES1:
1874 case RENDERPATH_SOFT:
1879 void R_GLSL_DumpShader_f(void)
1884 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1887 FS_Print(file, "/* The engine may define the following macros:\n");
1888 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889 for (i = 0;i < SHADERMODE_COUNT;i++)
1890 FS_Print(file, glslshadermodeinfo[i].pretext);
1891 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892 FS_Print(file, shaderpermutationinfo[i].pretext);
1893 FS_Print(file, "*/\n");
1894 FS_Print(file, builtinshaderstring);
1896 Con_Printf("glsl/default.glsl written\n");
1899 Con_Printf("failed to write to glsl/default.glsl\n");
1901 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1904 FS_Print(file, "/* The engine may define the following macros:\n");
1905 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1906 for (i = 0;i < SHADERMODE_COUNT;i++)
1907 FS_Print(file, hlslshadermodeinfo[i].pretext);
1908 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1909 FS_Print(file, shaderpermutationinfo[i].pretext);
1910 FS_Print(file, "*/\n");
1911 FS_Print(file, builtinhlslshaderstring);
1913 Con_Printf("hlsl/default.hlsl written\n");
1916 Con_Printf("failed to write to hlsl/default.hlsl\n");
1919 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1921 unsigned int permutation = 0;
1922 if (r_trippy.integer && !notrippy)
1923 permutation |= SHADERPERMUTATION_TRIPPY;
1924 permutation |= SHADERPERMUTATION_VIEWTINT;
1926 permutation |= SHADERPERMUTATION_DIFFUSE;
1928 permutation |= SHADERPERMUTATION_SPECULAR;
1929 if (texturemode == GL_MODULATE)
1930 permutation |= SHADERPERMUTATION_COLORMAPPING;
1931 else if (texturemode == GL_ADD)
1932 permutation |= SHADERPERMUTATION_GLOW;
1933 else if (texturemode == GL_DECAL)
1934 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1935 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1936 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1938 texturemode = GL_MODULATE;
1939 if (vid.allowalphatocoverage)
1940 GL_AlphaToCoverage(false);
1941 switch (vid.renderpath)
1943 case RENDERPATH_D3D9:
1945 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1946 R_Mesh_TexBind(GL20TU_FIRST , first );
1947 R_Mesh_TexBind(GL20TU_SECOND, second);
1948 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1949 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1952 case RENDERPATH_D3D10:
1953 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955 case RENDERPATH_D3D11:
1956 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958 case RENDERPATH_GL20:
1959 case RENDERPATH_GLES2:
1960 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1961 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1962 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1963 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1964 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1966 case RENDERPATH_GL13:
1967 case RENDERPATH_GLES1:
1968 R_Mesh_TexBind(0, first );
1969 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1970 R_Mesh_TexBind(1, second);
1972 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1974 case RENDERPATH_GL11:
1975 R_Mesh_TexBind(0, first );
1977 case RENDERPATH_SOFT:
1978 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1979 R_Mesh_TexBind(GL20TU_FIRST , first );
1980 R_Mesh_TexBind(GL20TU_SECOND, second);
1985 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1987 unsigned int permutation = 0;
1988 if (r_trippy.integer && !notrippy)
1989 permutation |= SHADERPERMUTATION_TRIPPY;
1990 if (vid.allowalphatocoverage)
1991 GL_AlphaToCoverage(false);
1992 switch (vid.renderpath)
1994 case RENDERPATH_D3D9:
1996 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1999 case RENDERPATH_D3D10:
2000 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2002 case RENDERPATH_D3D11:
2003 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2005 case RENDERPATH_GL20:
2006 case RENDERPATH_GLES2:
2007 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2009 case RENDERPATH_GL13:
2010 case RENDERPATH_GLES1:
2011 R_Mesh_TexBind(0, 0);
2012 R_Mesh_TexBind(1, 0);
2014 case RENDERPATH_GL11:
2015 R_Mesh_TexBind(0, 0);
2017 case RENDERPATH_SOFT:
2018 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2023 void R_SetupShader_ShowDepth(qboolean notrippy)
2025 int permutation = 0;
2026 if (r_trippy.integer && !notrippy)
2027 permutation |= SHADERPERMUTATION_TRIPPY;
2028 if (vid.allowalphatocoverage)
2029 GL_AlphaToCoverage(false);
2030 switch (vid.renderpath)
2032 case RENDERPATH_D3D9:
2034 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2037 case RENDERPATH_D3D10:
2038 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2040 case RENDERPATH_D3D11:
2041 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2043 case RENDERPATH_GL20:
2044 case RENDERPATH_GLES2:
2045 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2047 case RENDERPATH_GL13:
2048 case RENDERPATH_GLES1:
2050 case RENDERPATH_GL11:
2052 case RENDERPATH_SOFT:
2053 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2058 extern qboolean r_shadow_usingdeferredprepass;
2059 extern cvar_t r_shadow_deferred_8bitrange;
2060 extern rtexture_t *r_shadow_attenuationgradienttexture;
2061 extern rtexture_t *r_shadow_attenuation2dtexture;
2062 extern rtexture_t *r_shadow_attenuation3dtexture;
2063 extern qboolean r_shadow_usingshadowmap2d;
2064 extern qboolean r_shadow_usingshadowmaportho;
2065 extern float r_shadow_shadowmap_texturescale[2];
2066 extern float r_shadow_shadowmap_parameters[4];
2067 extern qboolean r_shadow_shadowmapvsdct;
2068 extern qboolean r_shadow_shadowmapsampler;
2069 extern int r_shadow_shadowmappcf;
2070 extern rtexture_t *r_shadow_shadowmap2dtexture;
2071 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2072 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2073 extern matrix4x4_t r_shadow_shadowmapmatrix;
2074 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2075 extern int r_shadow_prepass_width;
2076 extern int r_shadow_prepass_height;
2077 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2078 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2079 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2080 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2081 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2083 #define BLENDFUNC_ALLOWS_COLORMOD 1
2084 #define BLENDFUNC_ALLOWS_FOG 2
2085 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2086 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2087 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2088 static int R_BlendFuncFlags(int src, int dst)
2092 // a blendfunc allows colormod if:
2093 // a) it can never keep the destination pixel invariant, or
2094 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2095 // this is to prevent unintended side effects from colormod
2097 // a blendfunc allows fog if:
2098 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2099 // this is to prevent unintended side effects from fog
2101 // these checks are the output of fogeval.pl
2103 r |= BLENDFUNC_ALLOWS_COLORMOD;
2104 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2106 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2108 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2110 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2111 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2112 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2113 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2114 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2115 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2117 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2118 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2119 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2120 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2121 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2122 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2123 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2124 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2129 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)
2131 // select a permutation of the lighting shader appropriate to this
2132 // combination of texture, entity, light source, and fogging, only use the
2133 // minimum features necessary to avoid wasting rendering time in the
2134 // fragment shader on features that are not being used
2135 unsigned int permutation = 0;
2136 unsigned int mode = 0;
2138 static float dummy_colormod[3] = {1, 1, 1};
2139 float *colormod = rsurface.colormod;
2141 matrix4x4_t tempmatrix;
2142 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2143 if (r_trippy.integer && !notrippy)
2144 permutation |= SHADERPERMUTATION_TRIPPY;
2145 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2146 permutation |= SHADERPERMUTATION_ALPHAKILL;
2147 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2148 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2149 if (rsurfacepass == RSURFPASS_BACKGROUND)
2151 // distorted background
2152 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2154 mode = SHADERMODE_WATER;
2155 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2157 // this is the right thing to do for wateralpha
2158 GL_BlendFunc(GL_ONE, GL_ZERO);
2159 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2163 // this is the right thing to do for entity alpha
2164 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2165 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2168 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2170 mode = SHADERMODE_REFRACTION;
2171 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2172 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2176 mode = SHADERMODE_GENERIC;
2177 permutation |= SHADERPERMUTATION_DIFFUSE;
2178 GL_BlendFunc(GL_ONE, GL_ZERO);
2179 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2181 if (vid.allowalphatocoverage)
2182 GL_AlphaToCoverage(false);
2184 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2186 if (r_glsl_offsetmapping.integer)
2188 switch(rsurface.texture->offsetmapping)
2190 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2191 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2192 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2193 case OFFSETMAPPING_OFF: break;
2196 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2197 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2198 // normalmap (deferred prepass), may use alpha test on diffuse
2199 mode = SHADERMODE_DEFERREDGEOMETRY;
2200 GL_BlendFunc(GL_ONE, GL_ZERO);
2201 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2202 if (vid.allowalphatocoverage)
2203 GL_AlphaToCoverage(false);
2205 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2207 if (r_glsl_offsetmapping.integer)
2209 switch(rsurface.texture->offsetmapping)
2211 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2212 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2213 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2214 case OFFSETMAPPING_OFF: break;
2217 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2218 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2220 mode = SHADERMODE_LIGHTSOURCE;
2221 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2222 permutation |= SHADERPERMUTATION_CUBEFILTER;
2223 if (diffusescale > 0)
2224 permutation |= SHADERPERMUTATION_DIFFUSE;
2225 if (specularscale > 0)
2226 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2227 if (r_refdef.fogenabled)
2228 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2229 if (rsurface.texture->colormapping)
2230 permutation |= SHADERPERMUTATION_COLORMAPPING;
2231 if (r_shadow_usingshadowmap2d)
2233 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2234 if(r_shadow_shadowmapvsdct)
2235 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2237 if (r_shadow_shadowmapsampler)
2238 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2239 if (r_shadow_shadowmappcf > 1)
2240 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2241 else if (r_shadow_shadowmappcf)
2242 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2244 if (rsurface.texture->reflectmasktexture)
2245 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2246 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2247 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2248 if (vid.allowalphatocoverage)
2249 GL_AlphaToCoverage(false);
2251 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2253 if (r_glsl_offsetmapping.integer)
2255 switch(rsurface.texture->offsetmapping)
2257 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2258 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2259 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2260 case OFFSETMAPPING_OFF: break;
2263 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2264 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2265 // unshaded geometry (fullbright or ambient model lighting)
2266 mode = SHADERMODE_FLATCOLOR;
2267 ambientscale = diffusescale = specularscale = 0;
2268 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2269 permutation |= SHADERPERMUTATION_GLOW;
2270 if (r_refdef.fogenabled)
2271 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2272 if (rsurface.texture->colormapping)
2273 permutation |= SHADERPERMUTATION_COLORMAPPING;
2274 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2276 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2277 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2279 if (r_shadow_shadowmapsampler)
2280 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2281 if (r_shadow_shadowmappcf > 1)
2282 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2283 else if (r_shadow_shadowmappcf)
2284 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2286 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2287 permutation |= SHADERPERMUTATION_REFLECTION;
2288 if (rsurface.texture->reflectmasktexture)
2289 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2290 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2291 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2292 // when using alphatocoverage, we don't need alphakill
2293 if (vid.allowalphatocoverage)
2295 if (r_transparent_alphatocoverage.integer)
2297 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2298 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2301 GL_AlphaToCoverage(false);
2304 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2306 if (r_glsl_offsetmapping.integer)
2308 switch(rsurface.texture->offsetmapping)
2310 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2311 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2312 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2313 case OFFSETMAPPING_OFF: break;
2316 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2317 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2318 // directional model lighting
2319 mode = SHADERMODE_LIGHTDIRECTION;
2320 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2321 permutation |= SHADERPERMUTATION_GLOW;
2322 permutation |= SHADERPERMUTATION_DIFFUSE;
2323 if (specularscale > 0)
2324 permutation |= SHADERPERMUTATION_SPECULAR;
2325 if (r_refdef.fogenabled)
2326 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2327 if (rsurface.texture->colormapping)
2328 permutation |= SHADERPERMUTATION_COLORMAPPING;
2329 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2331 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2332 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2334 if (r_shadow_shadowmapsampler)
2335 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2336 if (r_shadow_shadowmappcf > 1)
2337 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2338 else if (r_shadow_shadowmappcf)
2339 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2341 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2342 permutation |= SHADERPERMUTATION_REFLECTION;
2343 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2344 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2345 if (rsurface.texture->reflectmasktexture)
2346 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2347 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2349 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2350 if (r_shadow_bouncegriddirectional)
2351 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2353 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2354 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2355 // when using alphatocoverage, we don't need alphakill
2356 if (vid.allowalphatocoverage)
2358 if (r_transparent_alphatocoverage.integer)
2360 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2361 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2364 GL_AlphaToCoverage(false);
2367 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2369 if (r_glsl_offsetmapping.integer)
2371 switch(rsurface.texture->offsetmapping)
2373 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2374 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2375 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2376 case OFFSETMAPPING_OFF: break;
2379 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2380 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2381 // ambient model lighting
2382 mode = SHADERMODE_LIGHTDIRECTION;
2383 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2384 permutation |= SHADERPERMUTATION_GLOW;
2385 if (r_refdef.fogenabled)
2386 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2387 if (rsurface.texture->colormapping)
2388 permutation |= SHADERPERMUTATION_COLORMAPPING;
2389 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2391 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2392 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2394 if (r_shadow_shadowmapsampler)
2395 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2396 if (r_shadow_shadowmappcf > 1)
2397 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2398 else if (r_shadow_shadowmappcf)
2399 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2401 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2402 permutation |= SHADERPERMUTATION_REFLECTION;
2403 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2404 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2405 if (rsurface.texture->reflectmasktexture)
2406 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2407 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2409 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2410 if (r_shadow_bouncegriddirectional)
2411 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2413 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415 // when using alphatocoverage, we don't need alphakill
2416 if (vid.allowalphatocoverage)
2418 if (r_transparent_alphatocoverage.integer)
2420 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2421 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2424 GL_AlphaToCoverage(false);
2429 if (r_glsl_offsetmapping.integer)
2431 switch(rsurface.texture->offsetmapping)
2433 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2434 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2435 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436 case OFFSETMAPPING_OFF: break;
2439 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2440 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2442 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2443 permutation |= SHADERPERMUTATION_GLOW;
2444 if (r_refdef.fogenabled)
2445 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2446 if (rsurface.texture->colormapping)
2447 permutation |= SHADERPERMUTATION_COLORMAPPING;
2448 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2450 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2451 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2453 if (r_shadow_shadowmapsampler)
2454 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2455 if (r_shadow_shadowmappcf > 1)
2456 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2457 else if (r_shadow_shadowmappcf)
2458 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2460 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2461 permutation |= SHADERPERMUTATION_REFLECTION;
2462 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2463 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2464 if (rsurface.texture->reflectmasktexture)
2465 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2466 if (FAKELIGHT_ENABLED)
2468 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2469 mode = SHADERMODE_FAKELIGHT;
2470 permutation |= SHADERPERMUTATION_DIFFUSE;
2471 if (specularscale > 0)
2472 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2474 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2476 // deluxemapping (light direction texture)
2477 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2478 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2480 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2481 permutation |= SHADERPERMUTATION_DIFFUSE;
2482 if (specularscale > 0)
2483 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2485 else if (r_glsl_deluxemapping.integer >= 2)
2487 // fake deluxemapping (uniform light direction in tangentspace)
2488 if (rsurface.uselightmaptexture)
2489 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2491 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2492 permutation |= SHADERPERMUTATION_DIFFUSE;
2493 if (specularscale > 0)
2494 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2496 else if (rsurface.uselightmaptexture)
2498 // ordinary lightmapping (q1bsp, q3bsp)
2499 mode = SHADERMODE_LIGHTMAP;
2503 // ordinary vertex coloring (q3bsp)
2504 mode = SHADERMODE_VERTEXCOLOR;
2506 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2508 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2509 if (r_shadow_bouncegriddirectional)
2510 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2512 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2513 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2514 // when using alphatocoverage, we don't need alphakill
2515 if (vid.allowalphatocoverage)
2517 if (r_transparent_alphatocoverage.integer)
2519 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2520 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2523 GL_AlphaToCoverage(false);
2526 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2527 colormod = dummy_colormod;
2528 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2529 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2530 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2531 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2532 switch(vid.renderpath)
2534 case RENDERPATH_D3D9:
2536 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);
2537 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2538 R_SetupShader_SetPermutationHLSL(mode, permutation);
2539 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2540 if (mode == SHADERMODE_LIGHTSOURCE)
2542 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2543 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2547 if (mode == SHADERMODE_LIGHTDIRECTION)
2549 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2552 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2553 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2554 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2555 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2556 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2558 if (mode == SHADERMODE_LIGHTSOURCE)
2560 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2561 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2562 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2563 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2564 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2566 // additive passes are only darkened by fog, not tinted
2567 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2568 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2572 if (mode == SHADERMODE_FLATCOLOR)
2574 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2576 else if (mode == SHADERMODE_LIGHTDIRECTION)
2578 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]);
2579 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2580 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);
2581 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);
2582 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2583 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2584 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2588 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2589 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2590 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);
2591 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);
2592 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2594 // additive passes are only darkened by fog, not tinted
2595 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2596 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2598 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2599 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);
2600 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2601 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2602 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2603 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2604 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2605 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2606 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2607 if (mode == SHADERMODE_WATER)
2608 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2610 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2611 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2612 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2613 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));
2614 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2615 if (rsurface.texture->pantstexture)
2616 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2618 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2619 if (rsurface.texture->shirttexture)
2620 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2622 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2623 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2624 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2625 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2626 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2627 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2628 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2629 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2630 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2631 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2633 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer)
2634 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias / 255)
2635 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2636 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2638 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2639 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2640 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2641 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2642 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2643 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2644 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2645 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2646 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2647 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2648 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2649 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2650 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2651 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2652 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2653 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2654 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2655 if (rsurfacepass == RSURFPASS_BACKGROUND)
2657 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2658 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2659 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2663 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2665 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2666 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2667 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2668 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2669 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2671 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2672 if (rsurface.rtlight)
2674 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2675 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2680 case RENDERPATH_D3D10:
2681 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2683 case RENDERPATH_D3D11:
2684 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2686 case RENDERPATH_GL20:
2687 case RENDERPATH_GLES2:
2688 if (!vid.useinterleavedarrays)
2690 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);
2691 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2692 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2693 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2694 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2695 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2696 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2697 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2701 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);
2702 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2704 R_SetupShader_SetPermutationGLSL(mode, permutation);
2705 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2706 if (mode == SHADERMODE_LIGHTSOURCE)
2708 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2709 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2710 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2711 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2712 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2713 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);
2715 // additive passes are only darkened by fog, not tinted
2716 if (r_glsl_permutation->loc_FogColor >= 0)
2717 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2718 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);
2722 if (mode == SHADERMODE_FLATCOLOR)
2724 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2726 else if (mode == SHADERMODE_LIGHTDIRECTION)
2728 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]);
2729 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]);
2730 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);
2731 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);
2732 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);
2733 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]);
2734 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]);
2738 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]);
2739 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]);
2740 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);
2741 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);
2742 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);
2744 // additive passes are only darkened by fog, not tinted
2745 if (r_glsl_permutation->loc_FogColor >= 0)
2747 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2748 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2750 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2752 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);
2753 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]);
2754 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]);
2755 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]);
2756 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]);
2757 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2758 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2759 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);
2760 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]);
2762 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2763 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2764 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2765 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]);
2766 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]);
2768 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2769 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));
2770 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2771 if (r_glsl_permutation->loc_Color_Pants >= 0)
2773 if (rsurface.texture->pantstexture)
2774 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2776 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2778 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2780 if (rsurface.texture->shirttexture)
2781 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2783 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2785 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]);
2786 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2787 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2788 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2789 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2790 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2791 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2792 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2793 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2795 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2796 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias / 255);
2797 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]);
2798 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2799 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);}
2800 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2802 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2803 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2804 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2805 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2806 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2807 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2808 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2809 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2810 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2811 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2812 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2813 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2814 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2815 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2816 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);
2817 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2818 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2819 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2820 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2821 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2822 if (rsurfacepass == RSURFPASS_BACKGROUND)
2824 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);
2825 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);
2826 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);
2830 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);
2832 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2833 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2834 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2835 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2836 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2838 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2839 if (rsurface.rtlight)
2841 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2842 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2845 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2848 case RENDERPATH_GL11:
2849 case RENDERPATH_GL13:
2850 case RENDERPATH_GLES1:
2852 case RENDERPATH_SOFT:
2853 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);
2854 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2855 R_SetupShader_SetPermutationSoft(mode, permutation);
2856 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2857 if (mode == SHADERMODE_LIGHTSOURCE)
2859 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2860 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2861 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2862 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2863 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2864 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2866 // additive passes are only darkened by fog, not tinted
2867 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2868 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2872 if (mode == SHADERMODE_FLATCOLOR)
2874 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2876 else if (mode == SHADERMODE_LIGHTDIRECTION)
2878 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]);
2879 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2880 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);
2881 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);
2882 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2883 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]);
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2888 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2889 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2890 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);
2891 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);
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2894 // additive passes are only darkened by fog, not tinted
2895 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2896 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2898 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2899 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);
2900 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2901 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2902 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]);
2903 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]);
2904 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2905 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2906 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2907 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2909 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2910 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2911 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2912 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2913 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]);
2915 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2916 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));
2917 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2918 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2920 if (rsurface.texture->pantstexture)
2921 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2923 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2925 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2927 if (rsurface.texture->shirttexture)
2928 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2930 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2932 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2933 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2934 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2935 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2936 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2937 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2938 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2939 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2940 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2942 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2943 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias / 255);
2944 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2945 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2947 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2948 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2949 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2950 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2951 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2952 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2953 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2954 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2955 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2956 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2957 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2958 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2959 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2960 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2961 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2962 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2963 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2964 if (rsurfacepass == RSURFPASS_BACKGROUND)
2966 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2967 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2968 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2972 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2974 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2975 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2976 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2977 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2978 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2980 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2981 if (rsurface.rtlight)
2983 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2984 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2991 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2993 // select a permutation of the lighting shader appropriate to this
2994 // combination of texture, entity, light source, and fogging, only use the
2995 // minimum features necessary to avoid wasting rendering time in the
2996 // fragment shader on features that are not being used
2997 unsigned int permutation = 0;
2998 unsigned int mode = 0;
2999 const float *lightcolorbase = rtlight->currentcolor;
3000 float ambientscale = rtlight->ambientscale;
3001 float diffusescale = rtlight->diffusescale;
3002 float specularscale = rtlight->specularscale;
3003 // this is the location of the light in view space
3004 vec3_t viewlightorigin;
3005 // this transforms from view space (camera) to light space (cubemap)
3006 matrix4x4_t viewtolight;
3007 matrix4x4_t lighttoview;
3008 float viewtolight16f[16];
3009 float range = 1.0f / r_shadow_deferred_8bitrange.value;
3011 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3012 if (rtlight->currentcubemap != r_texture_whitecube)
3013 permutation |= SHADERPERMUTATION_CUBEFILTER;
3014 if (diffusescale > 0)
3015 permutation |= SHADERPERMUTATION_DIFFUSE;
3016 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3017 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3018 if (r_shadow_usingshadowmap2d)
3020 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3021 if (r_shadow_shadowmapvsdct)
3022 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3024 if (r_shadow_shadowmapsampler)
3025 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3026 if (r_shadow_shadowmappcf > 1)
3027 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3028 else if (r_shadow_shadowmappcf)
3029 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3031 if (vid.allowalphatocoverage)
3032 GL_AlphaToCoverage(false);
3033 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3034 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3035 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3036 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3037 switch(vid.renderpath)
3039 case RENDERPATH_D3D9:
3041 R_SetupShader_SetPermutationHLSL(mode, permutation);
3042 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3043 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3044 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3045 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3046 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3047 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3048 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3049 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);
3050 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3051 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3053 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3054 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3055 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3056 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3057 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3058 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3061 case RENDERPATH_D3D10:
3062 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3064 case RENDERPATH_D3D11:
3065 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3067 case RENDERPATH_GL20:
3068 case RENDERPATH_GLES2:
3069 R_SetupShader_SetPermutationGLSL(mode, permutation);
3070 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3071 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3072 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);
3073 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);
3074 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);
3075 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]);
3076 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]);
3077 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);
3078 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]);
3079 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3081 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3082 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3083 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3084 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3085 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3086 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3088 case RENDERPATH_GL11:
3089 case RENDERPATH_GL13:
3090 case RENDERPATH_GLES1:
3092 case RENDERPATH_SOFT:
3093 R_SetupShader_SetPermutationGLSL(mode, permutation);
3094 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3095 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3096 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3097 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3098 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3099 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3100 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]);
3101 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);
3102 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3103 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3105 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3106 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3107 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3108 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3109 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3110 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3115 #define SKINFRAME_HASH 1024
3119 int loadsequence; // incremented each level change
3120 memexpandablearray_t array;
3121 skinframe_t *hash[SKINFRAME_HASH];
3124 r_skinframe_t r_skinframe;
3126 void R_SkinFrame_PrepareForPurge(void)
3128 r_skinframe.loadsequence++;
3129 // wrap it without hitting zero
3130 if (r_skinframe.loadsequence >= 200)
3131 r_skinframe.loadsequence = 1;
3134 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3138 // mark the skinframe as used for the purging code
3139 skinframe->loadsequence = r_skinframe.loadsequence;
3142 void R_SkinFrame_Purge(void)
3146 for (i = 0;i < SKINFRAME_HASH;i++)
3148 for (s = r_skinframe.hash[i];s;s = s->next)
3150 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3152 if (s->merged == s->base)
3154 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3155 R_PurgeTexture(s->stain );s->stain = NULL;
3156 R_PurgeTexture(s->merged);s->merged = NULL;
3157 R_PurgeTexture(s->base );s->base = NULL;
3158 R_PurgeTexture(s->pants );s->pants = NULL;
3159 R_PurgeTexture(s->shirt );s->shirt = NULL;
3160 R_PurgeTexture(s->nmap );s->nmap = NULL;
3161 R_PurgeTexture(s->gloss );s->gloss = NULL;
3162 R_PurgeTexture(s->glow );s->glow = NULL;
3163 R_PurgeTexture(s->fog );s->fog = NULL;
3164 R_PurgeTexture(s->reflect);s->reflect = NULL;
3165 s->loadsequence = 0;
3171 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3173 char basename[MAX_QPATH];
3175 Image_StripImageExtension(name, basename, sizeof(basename));
3177 if( last == NULL ) {
3179 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3180 item = r_skinframe.hash[hashindex];
3185 // linearly search through the hash bucket
3186 for( ; item ; item = item->next ) {
3187 if( !strcmp( item->basename, basename ) ) {
3194 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3198 char basename[MAX_QPATH];
3200 Image_StripImageExtension(name, basename, sizeof(basename));
3202 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3203 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3204 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3208 rtexture_t *dyntexture;
3209 // check whether its a dynamic texture
3210 dyntexture = CL_GetDynTexture( basename );
3211 if (!add && !dyntexture)
3213 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3214 memset(item, 0, sizeof(*item));
3215 strlcpy(item->basename, basename, sizeof(item->basename));
3216 item->base = dyntexture; // either NULL or dyntexture handle
3217 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3218 item->comparewidth = comparewidth;
3219 item->compareheight = compareheight;
3220 item->comparecrc = comparecrc;
3221 item->next = r_skinframe.hash[hashindex];
3222 r_skinframe.hash[hashindex] = item;
3224 else if (textureflags & TEXF_FORCE_RELOAD)
3226 rtexture_t *dyntexture;
3227 // check whether its a dynamic texture
3228 dyntexture = CL_GetDynTexture( basename );
3229 if (!add && !dyntexture)
3231 if (item->merged == item->base)
3232 item->merged = NULL;
3233 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3234 R_PurgeTexture(item->stain );item->stain = NULL;
3235 R_PurgeTexture(item->merged);item->merged = NULL;
3236 R_PurgeTexture(item->base );item->base = NULL;
3237 R_PurgeTexture(item->pants );item->pants = NULL;
3238 R_PurgeTexture(item->shirt );item->shirt = NULL;
3239 R_PurgeTexture(item->nmap );item->nmap = NULL;
3240 R_PurgeTexture(item->gloss );item->gloss = NULL;
3241 R_PurgeTexture(item->glow );item->glow = NULL;
3242 R_PurgeTexture(item->fog );item->fog = NULL;
3243 R_PurgeTexture(item->reflect);item->reflect = NULL;
3244 item->loadsequence = 0;
3246 else if( item->base == NULL )
3248 rtexture_t *dyntexture;
3249 // check whether its a dynamic texture
3250 // 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]
3251 dyntexture = CL_GetDynTexture( basename );
3252 item->base = dyntexture; // either NULL or dyntexture handle
3255 R_SkinFrame_MarkUsed(item);
3259 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3261 unsigned long long avgcolor[5], wsum; \
3269 for(pix = 0; pix < cnt; ++pix) \
3272 for(comp = 0; comp < 3; ++comp) \
3274 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3277 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3279 for(comp = 0; comp < 3; ++comp) \
3280 avgcolor[comp] += getpixel * w; \
3283 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3284 avgcolor[4] += getpixel; \
3286 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3288 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3289 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3290 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3291 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3294 extern cvar_t gl_picmip;
3295 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3298 unsigned char *pixels;
3299 unsigned char *bumppixels;
3300 unsigned char *basepixels = NULL;
3301 int basepixels_width = 0;
3302 int basepixels_height = 0;
3303 skinframe_t *skinframe;
3304 rtexture_t *ddsbase = NULL;
3305 qboolean ddshasalpha = false;
3306 float ddsavgcolor[4];
3307 char basename[MAX_QPATH];
3308 int miplevel = R_PicmipForFlags(textureflags);
3309 int savemiplevel = miplevel;
3312 if (cls.state == ca_dedicated)
3315 // return an existing skinframe if already loaded
3316 // if loading of the first image fails, don't make a new skinframe as it
3317 // would cause all future lookups of this to be missing
3318 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3319 if (skinframe && skinframe->base)
3322 Image_StripImageExtension(name, basename, sizeof(basename));
3324 // check for DDS texture file first
3325 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3327 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3328 if (basepixels == NULL)
3332 // FIXME handle miplevel
3334 if (developer_loading.integer)
3335 Con_Printf("loading skin \"%s\"\n", name);
3337 // we've got some pixels to store, so really allocate this new texture now
3339 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3340 textureflags &= ~TEXF_FORCE_RELOAD;
3341 skinframe->stain = NULL;
3342 skinframe->merged = NULL;
3343 skinframe->base = NULL;
3344 skinframe->pants = NULL;
3345 skinframe->shirt = NULL;
3346 skinframe->nmap = NULL;
3347 skinframe->gloss = NULL;
3348 skinframe->glow = NULL;
3349 skinframe->fog = NULL;
3350 skinframe->reflect = NULL;
3351 skinframe->hasalpha = false;
3355 skinframe->base = ddsbase;
3356 skinframe->hasalpha = ddshasalpha;
3357 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3358 if (r_loadfog && skinframe->hasalpha)
3359 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3360 //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]);
3364 basepixels_width = image_width;
3365 basepixels_height = image_height;
3366 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);
3367 if (textureflags & TEXF_ALPHA)
3369 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3371 if (basepixels[j] < 255)
3373 skinframe->hasalpha = true;
3377 if (r_loadfog && skinframe->hasalpha)
3379 // has transparent pixels
3380 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3381 for (j = 0;j < image_width * image_height * 4;j += 4)
3386 pixels[j+3] = basepixels[j+3];
3388 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);
3392 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3394 //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]);
3395 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3396 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3397 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3398 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3404 mymiplevel = savemiplevel;
3405 if (r_loadnormalmap)
3406 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);
3407 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3409 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3410 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3411 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3412 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3415 // _norm is the name used by tenebrae and has been adopted as standard
3416 if (r_loadnormalmap && skinframe->nmap == NULL)
3418 mymiplevel = savemiplevel;
3419 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3421 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);
3425 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3427 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3428 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3429 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);
3431 Mem_Free(bumppixels);
3433 else if (r_shadow_bumpscale_basetexture.value > 0)
3435 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3436 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3437 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);
3441 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3442 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3446 // _luma is supported only for tenebrae compatibility
3447 // _glow is the preferred name
3448 mymiplevel = savemiplevel;
3449 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))))
3451 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);
3453 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3454 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3456 Mem_Free(pixels);pixels = NULL;
3459 mymiplevel = savemiplevel;
3460 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3462 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);
3464 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3465 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3471 mymiplevel = savemiplevel;
3472 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3474 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);
3476 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3477 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3483 mymiplevel = savemiplevel;
3484 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3486 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);
3488 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3489 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3495 mymiplevel = savemiplevel;
3496 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3498 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);
3500 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3501 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3508 Mem_Free(basepixels);
3513 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3514 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3517 unsigned char *temp1, *temp2;
3518 skinframe_t *skinframe;
3520 if (cls.state == ca_dedicated)
3523 // if already loaded just return it, otherwise make a new skinframe
3524 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3525 if (skinframe && skinframe->base)
3527 textureflags &= ~TEXF_FORCE_RELOAD;
3529 skinframe->stain = NULL;
3530 skinframe->merged = NULL;
3531 skinframe->base = NULL;
3532 skinframe->pants = NULL;
3533 skinframe->shirt = NULL;
3534 skinframe->nmap = NULL;
3535 skinframe->gloss = NULL;
3536 skinframe->glow = NULL;
3537 skinframe->fog = NULL;
3538 skinframe->reflect = NULL;
3539 skinframe->hasalpha = false;
3541 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3545 if (developer_loading.integer)
3546 Con_Printf("loading 32bit skin \"%s\"\n", name);
3548 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3550 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3551 temp2 = temp1 + width * height * 4;
3552 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3553 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);
3556 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3557 if (textureflags & TEXF_ALPHA)
3559 for (i = 3;i < width * height * 4;i += 4)
3561 if (skindata[i] < 255)
3563 skinframe->hasalpha = true;
3567 if (r_loadfog && skinframe->hasalpha)
3569 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3570 memcpy(fogpixels, skindata, width * height * 4);
3571 for (i = 0;i < width * height * 4;i += 4)
3572 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3573 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3574 Mem_Free(fogpixels);
3578 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3579 //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]);
3584 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3588 skinframe_t *skinframe;
3590 if (cls.state == ca_dedicated)
3593 // if already loaded just return it, otherwise make a new skinframe
3594 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3595 if (skinframe && skinframe->base)
3597 textureflags &= ~TEXF_FORCE_RELOAD;
3599 skinframe->stain = NULL;
3600 skinframe->merged = NULL;
3601 skinframe->base = NULL;
3602 skinframe->pants = NULL;
3603 skinframe->shirt = NULL;
3604 skinframe->nmap = NULL;
3605 skinframe->gloss = NULL;
3606 skinframe->glow = NULL;
3607 skinframe->fog = NULL;
3608 skinframe->reflect = NULL;
3609 skinframe->hasalpha = false;
3611 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3615 if (developer_loading.integer)
3616 Con_Printf("loading quake skin \"%s\"\n", name);
3618 // 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)
3619 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3620 memcpy(skinframe->qpixels, skindata, width*height);
3621 skinframe->qwidth = width;
3622 skinframe->qheight = height;
3625 for (i = 0;i < width * height;i++)
3626 featuresmask |= palette_featureflags[skindata[i]];
3628 skinframe->hasalpha = false;
3629 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3630 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3631 skinframe->qgeneratemerged = true;
3632 skinframe->qgeneratebase = skinframe->qhascolormapping;
3633 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3635 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3636 //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]);
3641 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3645 unsigned char *skindata;
3647 if (!skinframe->qpixels)
3650 if (!skinframe->qhascolormapping)
3651 colormapped = false;
3655 if (!skinframe->qgeneratebase)
3660 if (!skinframe->qgeneratemerged)
3664 width = skinframe->qwidth;
3665 height = skinframe->qheight;
3666 skindata = skinframe->qpixels;
3668 if (skinframe->qgeneratenmap)
3670 unsigned char *temp1, *temp2;
3671 skinframe->qgeneratenmap = false;
3672 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3673 temp2 = temp1 + width * height * 4;
3674 // use either a custom palette or the quake palette
3675 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3676 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3677 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);
3681 if (skinframe->qgenerateglow)
3683 skinframe->qgenerateglow = false;
3684 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
3689 skinframe->qgeneratebase = false;
3690 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);
3691 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);
3692 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);
3696 skinframe->qgeneratemerged = false;
3697 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);
3700 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3702 Mem_Free(skinframe->qpixels);
3703 skinframe->qpixels = NULL;
3707 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)
3710 skinframe_t *skinframe;
3712 if (cls.state == ca_dedicated)
3715 // if already loaded just return it, otherwise make a new skinframe
3716 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3717 if (skinframe && skinframe->base)
3719 textureflags &= ~TEXF_FORCE_RELOAD;
3721 skinframe->stain = NULL;
3722 skinframe->merged = NULL;
3723 skinframe->base = NULL;
3724 skinframe->pants = NULL;
3725 skinframe->shirt = NULL;
3726 skinframe->nmap = NULL;
3727 skinframe->gloss = NULL;
3728 skinframe->glow = NULL;
3729 skinframe->fog = NULL;
3730 skinframe->reflect = NULL;
3731 skinframe->hasalpha = false;
3733 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3737 if (developer_loading.integer)
3738 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3740 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3741 if (textureflags & TEXF_ALPHA)
3743 for (i = 0;i < width * height;i++)
3745 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3747 skinframe->hasalpha = true;
3751 if (r_loadfog && skinframe->hasalpha)
3752 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3755 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3756 //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]);
3761 skinframe_t *R_SkinFrame_LoadMissing(void)
3763 skinframe_t *skinframe;
3765 if (cls.state == ca_dedicated)
3768 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3769 skinframe->stain = NULL;
3770 skinframe->merged = NULL;
3771 skinframe->base = NULL;
3772 skinframe->pants = NULL;
3773 skinframe->shirt = NULL;
3774 skinframe->nmap = NULL;
3775 skinframe->gloss = NULL;
3776 skinframe->glow = NULL;
3777 skinframe->fog = NULL;
3778 skinframe->reflect = NULL;
3779 skinframe->hasalpha = false;
3781 skinframe->avgcolor[0] = rand() / RAND_MAX;
3782 skinframe->avgcolor[1] = rand() / RAND_MAX;
3783 skinframe->avgcolor[2] = rand() / RAND_MAX;
3784 skinframe->avgcolor[3] = 1;
3789 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3790 typedef struct suffixinfo_s
3793 qboolean flipx, flipy, flipdiagonal;
3796 static suffixinfo_t suffix[3][6] =
3799 {"px", false, false, false},
3800 {"nx", false, false, false},
3801 {"py", false, false, false},
3802 {"ny", false, false, false},
3803 {"pz", false, false, false},
3804 {"nz", false, false, false}
3807 {"posx", false, false, false},
3808 {"negx", false, false, false},
3809 {"posy", false, false, false},
3810 {"negy", false, false, false},
3811 {"posz", false, false, false},
3812 {"negz", false, false, false}
3815 {"rt", true, false, true},
3816 {"lf", false, true, true},
3817 {"ft", true, true, false},
3818 {"bk", false, false, false},
3819 {"up", true, false, true},
3820 {"dn", true, false, true}
3824 static int componentorder[4] = {0, 1, 2, 3};
3826 rtexture_t *R_LoadCubemap(const char *basename)
3828 int i, j, cubemapsize;
3829 unsigned char *cubemappixels, *image_buffer;
3830 rtexture_t *cubemaptexture;
3832 // must start 0 so the first loadimagepixels has no requested width/height
3834 cubemappixels = NULL;
3835 cubemaptexture = NULL;
3836 // keep trying different suffix groups (posx, px, rt) until one loads
3837 for (j = 0;j < 3 && !cubemappixels;j++)
3839 // load the 6 images in the suffix group
3840 for (i = 0;i < 6;i++)
3842 // generate an image name based on the base and and suffix
3843 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3845 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3847 // an image loaded, make sure width and height are equal
3848 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3850 // if this is the first image to load successfully, allocate the cubemap memory
3851 if (!cubemappixels && image_width >= 1)
3853 cubemapsize = image_width;
3854 // note this clears to black, so unavailable sides are black
3855 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3857 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3859 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);
3862 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3864 Mem_Free(image_buffer);
3868 // if a cubemap loaded, upload it
3871 if (developer_loading.integer)
3872 Con_Printf("loading cubemap \"%s\"\n", basename);
3874 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);
3875 Mem_Free(cubemappixels);
3879 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3880 if (developer_loading.integer)
3882 Con_Printf("(tried tried images ");
3883 for (j = 0;j < 3;j++)
3884 for (i = 0;i < 6;i++)
3885 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3886 Con_Print(" and was unable to find any of them).\n");
3889 return cubemaptexture;
3892 rtexture_t *R_GetCubemap(const char *basename)
3895 for (i = 0;i < r_texture_numcubemaps;i++)
3896 if (r_texture_cubemaps[i] != NULL)
3897 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3898 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3899 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3900 return r_texture_whitecube;
3901 r_texture_numcubemaps++;
3902 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3903 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3904 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3905 return r_texture_cubemaps[i]->texture;
3908 void R_FreeCubemap(const char *basename)
3912 for (i = 0;i < r_texture_numcubemaps;i++)
3914 if (r_texture_cubemaps[i] != NULL)
3916 if (r_texture_cubemaps[i]->texture)
3918 if (developer_loading.integer)
3919 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3920 R_FreeTexture(r_texture_cubemaps[i]->texture);
3921 Mem_Free(r_texture_cubemaps[i]);
3922 r_texture_cubemaps[i] = NULL;
3928 void R_FreeCubemaps(void)
3931 for (i = 0;i < r_texture_numcubemaps;i++)
3933 if (developer_loading.integer)
3934 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3935 if (r_texture_cubemaps[i] != NULL)
3937 if (r_texture_cubemaps[i]->texture)
3938 R_FreeTexture(r_texture_cubemaps[i]->texture);
3939 Mem_Free(r_texture_cubemaps[i]);
3942 r_texture_numcubemaps = 0;
3945 void R_Main_FreeViewCache(void)
3947 if (r_refdef.viewcache.entityvisible)
3948 Mem_Free(r_refdef.viewcache.entityvisible);
3949 if (r_refdef.viewcache.world_pvsbits)
3950 Mem_Free(r_refdef.viewcache.world_pvsbits);
3951 if (r_refdef.viewcache.world_leafvisible)
3952 Mem_Free(r_refdef.viewcache.world_leafvisible);
3953 if (r_refdef.viewcache.world_surfacevisible)
3954 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3955 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3958 void R_Main_ResizeViewCache(void)
3960 int numentities = r_refdef.scene.numentities;
3961 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3962 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3963 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3964 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3965 if (r_refdef.viewcache.maxentities < numentities)
3967 r_refdef.viewcache.maxentities = numentities;
3968 if (r_refdef.viewcache.entityvisible)
3969 Mem_Free(r_refdef.viewcache.entityvisible);
3970 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3972 if (r_refdef.viewcache.world_numclusters != numclusters)
3974 r_refdef.viewcache.world_numclusters = numclusters;
3975 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3976 if (r_refdef.viewcache.world_pvsbits)
3977 Mem_Free(r_refdef.viewcache.world_pvsbits);
3978 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3980 if (r_refdef.viewcache.world_numleafs != numleafs)
3982 r_refdef.viewcache.world_numleafs = numleafs;
3983 if (r_refdef.viewcache.world_leafvisible)
3984 Mem_Free(r_refdef.viewcache.world_leafvisible);
3985 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3987 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3989 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3990 if (r_refdef.viewcache.world_surfacevisible)
3991 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3992 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3996 extern rtexture_t *loadingscreentexture;
3997 void gl_main_start(void)
3999 loadingscreentexture = NULL;
4000 r_texture_blanknormalmap = NULL;
4001 r_texture_white = NULL;
4002 r_texture_grey128 = NULL;
4003 r_texture_black = NULL;
4004 r_texture_whitecube = NULL;
4005 r_texture_normalizationcube = NULL;
4006 r_texture_fogattenuation = NULL;
4007 r_texture_fogheighttexture = NULL;
4008 r_texture_gammaramps = NULL;
4009 r_texture_numcubemaps = 0;
4011 r_loaddds = r_texture_dds_load.integer != 0;
4012 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4014 switch(vid.renderpath)
4016 case RENDERPATH_GL20:
4017 case RENDERPATH_D3D9:
4018 case RENDERPATH_D3D10:
4019 case RENDERPATH_D3D11:
4020 case RENDERPATH_SOFT:
4021 case RENDERPATH_GLES2:
4022 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4023 Cvar_SetValueQuick(&gl_combine, 1);
4024 Cvar_SetValueQuick(&r_glsl, 1);
4025 r_loadnormalmap = true;
4029 case RENDERPATH_GL13:
4030 case RENDERPATH_GLES1:
4031 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4032 Cvar_SetValueQuick(&gl_combine, 1);
4033 Cvar_SetValueQuick(&r_glsl, 0);
4034 r_loadnormalmap = false;
4035 r_loadgloss = false;
4038 case RENDERPATH_GL11:
4039 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4040 Cvar_SetValueQuick(&gl_combine, 0);
4041 Cvar_SetValueQuick(&r_glsl, 0);
4042 r_loadnormalmap = false;
4043 r_loadgloss = false;
4049 R_FrameData_Reset();
4053 memset(r_queries, 0, sizeof(r_queries));
4055 r_qwskincache = NULL;
4056 r_qwskincache_size = 0;
4058 // due to caching of texture_t references, the collision cache must be reset
4059 Collision_Cache_Reset(true);
4061 // set up r_skinframe loading system for textures
4062 memset(&r_skinframe, 0, sizeof(r_skinframe));
4063 r_skinframe.loadsequence = 1;
4064 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4066 r_main_texturepool = R_AllocTexturePool();
4067 R_BuildBlankTextures();
4069 if (vid.support.arb_texture_cube_map)
4072 R_BuildNormalizationCube();
4074 r_texture_fogattenuation = NULL;
4075 r_texture_fogheighttexture = NULL;
4076 r_texture_gammaramps = NULL;
4077 //r_texture_fogintensity = NULL;
4078 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4079 memset(&r_waterstate, 0, sizeof(r_waterstate));
4080 r_glsl_permutation = NULL;
4081 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4082 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4083 glslshaderstring = NULL;
4085 r_hlsl_permutation = NULL;
4086 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4087 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4089 hlslshaderstring = NULL;
4090 memset(&r_svbsp, 0, sizeof (r_svbsp));
4092 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4093 r_texture_numcubemaps = 0;
4095 r_refdef.fogmasktable_density = 0;
4098 void gl_main_shutdown(void)
4101 R_FrameData_Reset();
4103 R_Main_FreeViewCache();
4105 switch(vid.renderpath)
4107 case RENDERPATH_GL11:
4108 case RENDERPATH_GL13:
4109 case RENDERPATH_GL20:
4110 case RENDERPATH_GLES1:
4111 case RENDERPATH_GLES2:
4112 #ifdef GL_SAMPLES_PASSED_ARB
4114 qglDeleteQueriesARB(r_maxqueries, r_queries);
4117 case RENDERPATH_D3D9:
4118 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4120 case RENDERPATH_D3D10:
4121 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4123 case RENDERPATH_D3D11:
4124 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4126 case RENDERPATH_SOFT:
4132 memset(r_queries, 0, sizeof(r_queries));
4134 r_qwskincache = NULL;
4135 r_qwskincache_size = 0;
4137 // clear out the r_skinframe state
4138 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4139 memset(&r_skinframe, 0, sizeof(r_skinframe));
4142 Mem_Free(r_svbsp.nodes);
4143 memset(&r_svbsp, 0, sizeof (r_svbsp));
4144 R_FreeTexturePool(&r_main_texturepool);
4145 loadingscreentexture = NULL;
4146 r_texture_blanknormalmap = NULL;
4147 r_texture_white = NULL;
4148 r_texture_grey128 = NULL;
4149 r_texture_black = NULL;
4150 r_texture_whitecube = NULL;
4151 r_texture_normalizationcube = NULL;
4152 r_texture_fogattenuation = NULL;
4153 r_texture_fogheighttexture = NULL;
4154 r_texture_gammaramps = NULL;
4155 r_texture_numcubemaps = 0;
4156 //r_texture_fogintensity = NULL;
4157 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4158 memset(&r_waterstate, 0, sizeof(r_waterstate));
4161 r_glsl_permutation = NULL;
4162 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4163 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4164 glslshaderstring = NULL;
4166 r_hlsl_permutation = NULL;
4167 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4168 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4170 hlslshaderstring = NULL;
4173 extern void CL_ParseEntityLump(char *entitystring);
4174 void gl_main_newmap(void)
4176 // FIXME: move this code to client
4177 char *entities, entname[MAX_QPATH];
4179 Mem_Free(r_qwskincache);
4180 r_qwskincache = NULL;
4181 r_qwskincache_size = 0;
4184 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4185 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4187 CL_ParseEntityLump(entities);
4191 if (cl.worldmodel->brush.entities)
4192 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4194 R_Main_FreeViewCache();
4196 R_FrameData_Reset();
4199 void GL_Main_Init(void)
4201 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4203 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4204 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4205 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4206 if (gamemode == GAME_NEHAHRA)
4208 Cvar_RegisterVariable (&gl_fogenable);
4209 Cvar_RegisterVariable (&gl_fogdensity);
4210 Cvar_RegisterVariable (&gl_fogred);
4211 Cvar_RegisterVariable (&gl_foggreen);
4212 Cvar_RegisterVariable (&gl_fogblue);
4213 Cvar_RegisterVariable (&gl_fogstart);
4214 Cvar_RegisterVariable (&gl_fogend);
4215 Cvar_RegisterVariable (&gl_skyclip);
4217 Cvar_RegisterVariable(&r_motionblur);
4218 Cvar_RegisterVariable(&r_damageblur);
4219 Cvar_RegisterVariable(&r_motionblur_averaging);
4220 Cvar_RegisterVariable(&r_motionblur_randomize);
4221 Cvar_RegisterVariable(&r_motionblur_minblur);
4222 Cvar_RegisterVariable(&r_motionblur_maxblur);
4223 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4224 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4225 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4226 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4227 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4228 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4229 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4230 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4231 Cvar_RegisterVariable(&r_equalize_entities_by);
4232 Cvar_RegisterVariable(&r_equalize_entities_to);
4233 Cvar_RegisterVariable(&r_depthfirst);
4234 Cvar_RegisterVariable(&r_useinfinitefarclip);
4235 Cvar_RegisterVariable(&r_farclip_base);
4236 Cvar_RegisterVariable(&r_farclip_world);
4237 Cvar_RegisterVariable(&r_nearclip);
4238 Cvar_RegisterVariable(&r_deformvertexes);
4239 Cvar_RegisterVariable(&r_transparent);
4240 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4241 Cvar_RegisterVariable(&r_showoverdraw);
4242 Cvar_RegisterVariable(&r_showbboxes);
4243 Cvar_RegisterVariable(&r_showsurfaces);
4244 Cvar_RegisterVariable(&r_showtris);
4245 Cvar_RegisterVariable(&r_shownormals);
4246 Cvar_RegisterVariable(&r_showlighting);
4247 Cvar_RegisterVariable(&r_showshadowvolumes);
4248 Cvar_RegisterVariable(&r_showcollisionbrushes);
4249 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4250 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4251 Cvar_RegisterVariable(&r_showdisabledepthtest);
4252 Cvar_RegisterVariable(&r_drawportals);
4253 Cvar_RegisterVariable(&r_drawentities);
4254 Cvar_RegisterVariable(&r_draw2d);
4255 Cvar_RegisterVariable(&r_drawworld);
4256 Cvar_RegisterVariable(&r_cullentities_trace);
4257 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4258 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4259 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4260 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4261 Cvar_RegisterVariable(&r_sortentities);
4262 Cvar_RegisterVariable(&r_drawviewmodel);
4263 Cvar_RegisterVariable(&r_drawexteriormodel);
4264 Cvar_RegisterVariable(&r_speeds);
4265 Cvar_RegisterVariable(&r_fullbrights);
4266 Cvar_RegisterVariable(&r_wateralpha);
4267 Cvar_RegisterVariable(&r_dynamic);
4268 Cvar_RegisterVariable(&r_fakelight);
4269 Cvar_RegisterVariable(&r_fakelight_intensity);
4270 Cvar_RegisterVariable(&r_fullbright);
4271 Cvar_RegisterVariable(&r_shadows);
4272 Cvar_RegisterVariable(&r_shadows_darken);
4273 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4274 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4275 Cvar_RegisterVariable(&r_shadows_throwdistance);
4276 Cvar_RegisterVariable(&r_shadows_throwdirection);
4277 Cvar_RegisterVariable(&r_shadows_focus);
4278 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4279 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4280 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4281 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4282 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4283 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4284 Cvar_RegisterVariable(&r_fog_exp2);
4285 Cvar_RegisterVariable(&r_fog_clear);
4286 Cvar_RegisterVariable(&r_drawfog);
4287 Cvar_RegisterVariable(&r_transparentdepthmasking);
4288 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4289 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4290 Cvar_RegisterVariable(&r_texture_dds_load);
4291 Cvar_RegisterVariable(&r_texture_dds_save);
4292 Cvar_RegisterVariable(&r_textureunits);
4293 Cvar_RegisterVariable(&gl_combine);
4294 Cvar_RegisterVariable(&r_viewfbo);
4295 Cvar_RegisterVariable(&r_viewscale);
4296 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4297 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4298 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4299 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4300 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4301 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4302 Cvar_RegisterVariable(&r_glsl);
4303 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4304 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4305 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4306 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4307 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4308 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4309 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4310 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4311 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4312 Cvar_RegisterVariable(&r_glsl_postprocess);
4313 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4314 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4315 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4316 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4317 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4318 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4319 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4320 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4322 Cvar_RegisterVariable(&r_water);
4323 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4324 Cvar_RegisterVariable(&r_water_clippingplanebias);
4325 Cvar_RegisterVariable(&r_water_refractdistort);
4326 Cvar_RegisterVariable(&r_water_reflectdistort);
4327 Cvar_RegisterVariable(&r_water_scissormode);
4328 Cvar_RegisterVariable(&r_water_lowquality);
4330 Cvar_RegisterVariable(&r_lerpsprites);
4331 Cvar_RegisterVariable(&r_lerpmodels);
4332 Cvar_RegisterVariable(&r_lerplightstyles);
4333 Cvar_RegisterVariable(&r_waterscroll);
4334 Cvar_RegisterVariable(&r_bloom);
4335 Cvar_RegisterVariable(&r_bloom_colorscale);
4336 Cvar_RegisterVariable(&r_bloom_brighten);
4337 Cvar_RegisterVariable(&r_bloom_blur);
4338 Cvar_RegisterVariable(&r_bloom_resolution);
4339 Cvar_RegisterVariable(&r_bloom_colorexponent);
4340 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4341 Cvar_RegisterVariable(&r_hdr);
4342 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4343 Cvar_RegisterVariable(&r_hdr_glowintensity);
4344 Cvar_RegisterVariable(&r_hdr_range);
4345 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4346 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4347 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4348 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4349 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4350 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4351 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4352 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4353 Cvar_RegisterVariable(&developer_texturelogging);
4354 Cvar_RegisterVariable(&gl_lightmaps);
4355 Cvar_RegisterVariable(&r_test);
4356 Cvar_RegisterVariable(&r_glsl_saturation);
4357 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4358 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4359 Cvar_RegisterVariable(&r_framedatasize);
4360 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4361 Cvar_SetValue("r_fullbrights", 0);
4362 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4365 extern void R_Textures_Init(void);
4366 extern void GL_Draw_Init(void);
4367 extern void GL_Main_Init(void);
4368 extern void R_Shadow_Init(void);
4369 extern void R_Sky_Init(void);
4370 extern void GL_Surf_Init(void);
4371 extern void R_Particles_Init(void);
4372 extern void R_Explosion_Init(void);
4373 extern void gl_backend_init(void);
4374 extern void Sbar_Init(void);
4375 extern void R_LightningBeams_Init(void);
4376 extern void Mod_RenderInit(void);
4377 extern void Font_Init(void);
4379 void Render_Init(void)
4392 R_LightningBeams_Init();
4402 extern char *ENGINE_EXTENSIONS;
4405 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4406 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4407 gl_version = (const char *)qglGetString(GL_VERSION);
4408 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4412 if (!gl_platformextensions)
4413 gl_platformextensions = "";
4415 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4416 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4417 Con_Printf("GL_VERSION: %s\n", gl_version);
4418 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4419 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4421 VID_CheckExtensions();
4423 // LordHavoc: report supported extensions
4424 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4426 // clear to black (loading plaque will be seen over this)
4427 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4431 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4435 if (r_trippy.integer)
4437 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4439 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4442 p = r_refdef.view.frustum + i;
4447 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4451 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4455 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4459 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4463 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4467 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4471 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4475 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4483 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4487 if (r_trippy.integer)
4489 for (i = 0;i < numplanes;i++)
4496 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4500 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4504 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4508 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4512 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4516 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4520 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4524 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4532 //==================================================================================
4534 // LordHavoc: this stores temporary data used within the same frame
4536 typedef struct r_framedata_mem_s
4538 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4539 size_t size; // how much usable space
4540 size_t current; // how much space in use
4541 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4542 size_t wantedsize; // how much space was allocated
4543 unsigned char *data; // start of real data (16byte aligned)
4547 static r_framedata_mem_t *r_framedata_mem;
4549 void R_FrameData_Reset(void)
4551 while (r_framedata_mem)
4553 r_framedata_mem_t *next = r_framedata_mem->purge;
4554 Mem_Free(r_framedata_mem);
4555 r_framedata_mem = next;
4559 void R_FrameData_Resize(void)
4562 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4563 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4564 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4566 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4567 newmem->wantedsize = wantedsize;
4568 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4569 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4570 newmem->current = 0;
4572 newmem->purge = r_framedata_mem;
4573 r_framedata_mem = newmem;
4577 void R_FrameData_NewFrame(void)
4579 R_FrameData_Resize();
4580 if (!r_framedata_mem)
4582 // if we ran out of space on the last frame, free the old memory now
4583 while (r_framedata_mem->purge)
4585 // repeatedly remove the second item in the list, leaving only head
4586 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4587 Mem_Free(r_framedata_mem->purge);
4588 r_framedata_mem->purge = next;
4590 // reset the current mem pointer
4591 r_framedata_mem->current = 0;
4592 r_framedata_mem->mark = 0;
4595 void *R_FrameData_Alloc(size_t size)
4599 // align to 16 byte boundary - the data pointer is already aligned, so we
4600 // only need to ensure the size of every allocation is also aligned
4601 size = (size + 15) & ~15;
4603 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4605 // emergency - we ran out of space, allocate more memory
4606 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4607 R_FrameData_Resize();
4610 data = r_framedata_mem->data + r_framedata_mem->current;
4611 r_framedata_mem->current += size;
4613 // count the usage for stats
4614 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4615 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4617 return (void *)data;
4620 void *R_FrameData_Store(size_t size, void *data)
4622 void *d = R_FrameData_Alloc(size);
4624 memcpy(d, data, size);
4628 void R_FrameData_SetMark(void)
4630 if (!r_framedata_mem)
4632 r_framedata_mem->mark = r_framedata_mem->current;
4635 void R_FrameData_ReturnToMark(void)
4637 if (!r_framedata_mem)
4639 r_framedata_mem->current = r_framedata_mem->mark;
4642 //==================================================================================
4644 // LordHavoc: animcache originally written by Echon, rewritten since then
4647 * Animation cache prevents re-generating mesh data for an animated model
4648 * multiple times in one frame for lighting, shadowing, reflections, etc.
4651 void R_AnimCache_Free(void)
4655 void R_AnimCache_ClearCache(void)
4658 entity_render_t *ent;
4660 for (i = 0;i < r_refdef.scene.numentities;i++)
4662 ent = r_refdef.scene.entities[i];
4663 ent->animcache_vertex3f = NULL;
4664 ent->animcache_normal3f = NULL;
4665 ent->animcache_svector3f = NULL;
4666 ent->animcache_tvector3f = NULL;
4667 ent->animcache_vertexmesh = NULL;
4668 ent->animcache_vertex3fbuffer = NULL;
4669 ent->animcache_vertexmeshbuffer = NULL;
4673 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4677 // check if we need the meshbuffers
4678 if (!vid.useinterleavedarrays)
4681 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4682 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4683 // TODO: upload vertex3f buffer?
4684 if (ent->animcache_vertexmesh)
4686 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4687 for (i = 0;i < numvertices;i++)
4688 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4689 if (ent->animcache_svector3f)
4690 for (i = 0;i < numvertices;i++)
4691 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4692 if (ent->animcache_tvector3f)
4693 for (i = 0;i < numvertices;i++)
4694 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4695 if (ent->animcache_normal3f)
4696 for (i = 0;i < numvertices;i++)
4697 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4698 // TODO: upload vertexmeshbuffer?
4702 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4704 dp_model_t *model = ent->model;
4706 // see if it's already cached this frame
4707 if (ent->animcache_vertex3f)
4709 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4710 if (wantnormals || wanttangents)
4712 if (ent->animcache_normal3f)
4713 wantnormals = false;
4714 if (ent->animcache_svector3f)
4715 wanttangents = false;
4716 if (wantnormals || wanttangents)
4718 numvertices = model->surfmesh.num_vertices;
4720 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4723 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4724 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4726 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4727 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4733 // see if this ent is worth caching
4734 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4736 // get some memory for this entity and generate mesh data
4737 numvertices = model->surfmesh.num_vertices;
4738 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4740 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4743 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4744 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4746 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4747 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4752 void R_AnimCache_CacheVisibleEntities(void)
4755 qboolean wantnormals = true;
4756 qboolean wanttangents = !r_showsurfaces.integer;
4758 switch(vid.renderpath)
4760 case RENDERPATH_GL20:
4761 case RENDERPATH_D3D9:
4762 case RENDERPATH_D3D10:
4763 case RENDERPATH_D3D11:
4764 case RENDERPATH_GLES2:
4766 case RENDERPATH_GL11:
4767 case RENDERPATH_GL13:
4768 case RENDERPATH_GLES1:
4769 wanttangents = false;
4771 case RENDERPATH_SOFT:
4775 if (r_shownormals.integer)
4776 wanttangents = wantnormals = true;
4778 // TODO: thread this
4779 // NOTE: R_PrepareRTLights() also caches entities
4781 for (i = 0;i < r_refdef.scene.numentities;i++)
4782 if (r_refdef.viewcache.entityvisible[i])
4783 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4786 //==================================================================================
4788 extern cvar_t r_overheadsprites_pushback;
4790 static void R_View_UpdateEntityLighting (void)
4793 entity_render_t *ent;
4794 vec3_t tempdiffusenormal, avg;
4795 vec_t f, fa, fd, fdd;
4796 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4798 for (i = 0;i < r_refdef.scene.numentities;i++)
4800 ent = r_refdef.scene.entities[i];
4802 // skip unseen models
4803 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4807 if (ent->model && ent->model->brush.num_leafs)
4809 // TODO: use modellight for r_ambient settings on world?
4810 VectorSet(ent->modellight_ambient, 0, 0, 0);
4811 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4812 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4816 // fetch the lighting from the worldmodel data
4817 VectorClear(ent->modellight_ambient);
4818 VectorClear(ent->modellight_diffuse);
4819 VectorClear(tempdiffusenormal);
4820 if (ent->flags & RENDER_LIGHT)
4823 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4825 // complete lightning for lit sprites
4826 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4827 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4829 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4830 org[2] = org[2] + r_overheadsprites_pushback.value;
4831 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4834 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4836 if(ent->flags & RENDER_EQUALIZE)
4838 // first fix up ambient lighting...
4839 if(r_equalize_entities_minambient.value > 0)
4841 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4844 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4845 if(fa < r_equalize_entities_minambient.value * fd)
4848 // fa'/fd' = minambient
4849 // fa'+0.25*fd' = fa+0.25*fd
4851 // fa' = fd' * minambient
4852 // fd'*(0.25+minambient) = fa+0.25*fd
4854 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4855 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4857 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4858 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
4859 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4860 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4865 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4867 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4868 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4872 // adjust brightness and saturation to target
4873 avg[0] = avg[1] = avg[2] = fa / f;
4874 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4875 avg[0] = avg[1] = avg[2] = fd / f;
4876 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4882 VectorSet(ent->modellight_ambient, 1, 1, 1);
4884 // move the light direction into modelspace coordinates for lighting code
4885 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4886 if(VectorLength2(ent->modellight_lightdir) == 0)
4887 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4888 VectorNormalize(ent->modellight_lightdir);
4892 #define MAX_LINEOFSIGHTTRACES 64
4894 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4897 vec3_t boxmins, boxmaxs;
4900 dp_model_t *model = r_refdef.scene.worldmodel;
4902 if (!model || !model->brush.TraceLineOfSight)
4905 // expand the box a little
4906 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4907 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4908 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4909 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4910 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4911 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4913 // return true if eye is inside enlarged box
4914 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4918 VectorCopy(eye, start);
4919 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4920 if (model->brush.TraceLineOfSight(model, start, end))
4923 // try various random positions
4924 for (i = 0;i < numsamples;i++)
4926 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4927 if (model->brush.TraceLineOfSight(model, start, end))
4935 static void R_View_UpdateEntityVisible (void)
4940 entity_render_t *ent;
4942 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4943 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4944 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4945 : RENDER_EXTERIORMODEL;
4946 if (!r_drawviewmodel.integer)
4947 renderimask |= RENDER_VIEWMODEL;
4948 if (!r_drawexteriormodel.integer)
4949 renderimask |= RENDER_EXTERIORMODEL;
4950 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4952 // worldmodel can check visibility
4953 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4954 for (i = 0;i < r_refdef.scene.numentities;i++)
4956 ent = r_refdef.scene.entities[i];
4957 if (!(ent->flags & renderimask))
4958 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)))
4959 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))
4960 r_refdef.viewcache.entityvisible[i] = true;
4965 // no worldmodel or it can't check visibility
4966 for (i = 0;i < r_refdef.scene.numentities;i++)
4968 ent = r_refdef.scene.entities[i];
4969 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));
4972 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4973 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4975 for (i = 0;i < r_refdef.scene.numentities;i++)
4977 if (!r_refdef.viewcache.entityvisible[i])
4979 ent = r_refdef.scene.entities[i];
4980 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4982 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4984 continue; // temp entities do pvs only
4985 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4986 ent->last_trace_visibility = realtime;
4987 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4988 r_refdef.viewcache.entityvisible[i] = 0;
4994 /// only used if skyrendermasked, and normally returns false
4995 int R_DrawBrushModelsSky (void)
4998 entity_render_t *ent;
5001 for (i = 0;i < r_refdef.scene.numentities;i++)
5003 if (!r_refdef.viewcache.entityvisible[i])
5005 ent = r_refdef.scene.entities[i];
5006 if (!ent->model || !ent->model->DrawSky)
5008 ent->model->DrawSky(ent);
5014 static void R_DrawNoModel(entity_render_t *ent);
5015 static void R_DrawModels(void)
5018 entity_render_t *ent;
5020 for (i = 0;i < r_refdef.scene.numentities;i++)
5022 if (!r_refdef.viewcache.entityvisible[i])
5024 ent = r_refdef.scene.entities[i];
5025 r_refdef.stats.entities++;
5027 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5030 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5031 Con_Printf("R_DrawModels\n");
5032 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]);
5033 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);
5034 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);
5037 if (ent->model && ent->model->Draw != NULL)
5038 ent->model->Draw(ent);
5044 static void R_DrawModelsDepth(void)
5047 entity_render_t *ent;
5049 for (i = 0;i < r_refdef.scene.numentities;i++)
5051 if (!r_refdef.viewcache.entityvisible[i])
5053 ent = r_refdef.scene.entities[i];
5054 if (ent->model && ent->model->DrawDepth != NULL)
5055 ent->model->DrawDepth(ent);
5059 static void R_DrawModelsDebug(void)
5062 entity_render_t *ent;
5064 for (i = 0;i < r_refdef.scene.numentities;i++)
5066 if (!r_refdef.viewcache.entityvisible[i])
5068 ent = r_refdef.scene.entities[i];
5069 if (ent->model && ent->model->DrawDebug != NULL)
5070 ent->model->DrawDebug(ent);
5074 static void R_DrawModelsAddWaterPlanes(void)
5077 entity_render_t *ent;
5079 for (i = 0;i < r_refdef.scene.numentities;i++)
5081 if (!r_refdef.viewcache.entityvisible[i])
5083 ent = r_refdef.scene.entities[i];
5084 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5085 ent->model->DrawAddWaterPlanes(ent);
5089 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5091 if (r_hdr_irisadaptation.integer)
5095 vec3_t diffusenormal;
5099 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5100 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5101 brightness = max(0.0000001f, brightness);
5102 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5103 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5104 current = r_hdr_irisadaptation_value.value;
5106 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5107 else if (current > goal)
5108 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5109 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5110 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5112 else if (r_hdr_irisadaptation_value.value != 1.0f)
5113 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5116 static void R_View_SetFrustum(const int *scissor)
5119 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5120 vec3_t forward, left, up, origin, v;
5124 // flipped x coordinates (because x points left here)
5125 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5126 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5128 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5129 switch(vid.renderpath)
5131 case RENDERPATH_D3D9:
5132 case RENDERPATH_D3D10:
5133 case RENDERPATH_D3D11:
5134 // non-flipped y coordinates
5135 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5136 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5138 case RENDERPATH_SOFT:
5139 case RENDERPATH_GL11:
5140 case RENDERPATH_GL13:
5141 case RENDERPATH_GL20:
5142 case RENDERPATH_GLES1:
5143 case RENDERPATH_GLES2:
5144 // non-flipped y coordinates
5145 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5146 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5151 // we can't trust r_refdef.view.forward and friends in reflected scenes
5152 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5155 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5156 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5157 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5158 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5159 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5160 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5161 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5162 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5163 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5164 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5165 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5166 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5170 zNear = r_refdef.nearclip;
5171 nudge = 1.0 - 1.0 / (1<<23);
5172 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5173 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5174 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5175 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5176 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5177 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5178 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5179 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5185 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5186 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5187 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5188 r_refdef.view.frustum[0].dist = m[15] - m[12];
5190 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5191 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5192 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5193 r_refdef.view.frustum[1].dist = m[15] + m[12];
5195 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5196 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5197 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5198 r_refdef.view.frustum[2].dist = m[15] - m[13];
5200 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5201 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5202 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5203 r_refdef.view.frustum[3].dist = m[15] + m[13];
5205 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5206 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5207 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5208 r_refdef.view.frustum[4].dist = m[15] - m[14];
5210 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5211 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5212 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5213 r_refdef.view.frustum[5].dist = m[15] + m[14];
5216 if (r_refdef.view.useperspective)
5218 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5219 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]);
5220 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]);
5221 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]);
5222 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]);
5224 // then the normals from the corners relative to origin
5225 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5226 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5227 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5228 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5230 // in a NORMAL view, forward cross left == up
5231 // in a REFLECTED view, forward cross left == down
5232 // so our cross products above need to be adjusted for a left handed coordinate system
5233 CrossProduct(forward, left, v);
5234 if(DotProduct(v, up) < 0)
5236 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5237 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5238 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5239 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5242 // Leaving those out was a mistake, those were in the old code, and they
5243 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5244 // I couldn't reproduce it after adding those normalizations. --blub
5245 VectorNormalize(r_refdef.view.frustum[0].normal);
5246 VectorNormalize(r_refdef.view.frustum[1].normal);
5247 VectorNormalize(r_refdef.view.frustum[2].normal);
5248 VectorNormalize(r_refdef.view.frustum[3].normal);
5250 // make the corners absolute
5251 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5252 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5253 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5254 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5257 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5259 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5260 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5261 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5262 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5263 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5267 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5268 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5269 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5270 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5271 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5272 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5273 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5274 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5275 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5276 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5278 r_refdef.view.numfrustumplanes = 5;
5280 if (r_refdef.view.useclipplane)
5282 r_refdef.view.numfrustumplanes = 6;
5283 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5286 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5287 PlaneClassify(r_refdef.view.frustum + i);
5289 // LordHavoc: note to all quake engine coders, Quake had a special case
5290 // for 90 degrees which assumed a square view (wrong), so I removed it,
5291 // Quake2 has it disabled as well.
5293 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5294 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5295 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5296 //PlaneClassify(&frustum[0]);
5298 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5299 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5300 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5301 //PlaneClassify(&frustum[1]);
5303 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5304 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5305 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5306 //PlaneClassify(&frustum[2]);
5308 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5309 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5310 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5311 //PlaneClassify(&frustum[3]);
5314 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5315 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5316 //PlaneClassify(&frustum[4]);
5319 void R_View_UpdateWithScissor(const int *myscissor)
5321 R_Main_ResizeViewCache();
5322 R_View_SetFrustum(myscissor);
5323 R_View_WorldVisibility(r_refdef.view.useclipplane);
5324 R_View_UpdateEntityVisible();
5325 R_View_UpdateEntityLighting();
5328 void R_View_Update(void)
5330 R_Main_ResizeViewCache();
5331 R_View_SetFrustum(NULL);
5332 R_View_WorldVisibility(r_refdef.view.useclipplane);
5333 R_View_UpdateEntityVisible();
5334 R_View_UpdateEntityLighting();
5337 float viewscalefpsadjusted = 1.0f;
5339 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5341 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5342 scale = bound(0.03125f, scale, 1.0f);
5343 *outwidth = (int)ceil(width * scale);
5344 *outheight = (int)ceil(height * scale);
5347 void R_Mesh_SetMainRenderTargets(void)
5349 if (r_bloomstate.fbo_framebuffer)
5350 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5352 R_Mesh_ResetRenderTargets();
5355 void R_SetupView(qboolean allowwaterclippingplane)
5357 const float *customclipplane = NULL;
5359 int scaledwidth, scaledheight;
5360 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5362 // LordHavoc: couldn't figure out how to make this approach the
5363 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5364 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5365 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5366 dist = r_refdef.view.clipplane.dist;
5367 plane[0] = r_refdef.view.clipplane.normal[0];
5368 plane[1] = r_refdef.view.clipplane.normal[1];
5369 plane[2] = r_refdef.view.clipplane.normal[2];
5371 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5374 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5375 if (!r_refdef.view.useperspective)
5376 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);
5377 else if (vid.stencil && r_useinfinitefarclip.integer)
5378 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);
5380 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);
5381 R_Mesh_SetMainRenderTargets();
5382 R_SetViewport(&r_refdef.view.viewport);
5383 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5385 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5386 float screenplane[4];
5387 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5388 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5389 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5390 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5391 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5395 void R_EntityMatrix(const matrix4x4_t *matrix)
5397 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5399 gl_modelmatrixchanged = false;
5400 gl_modelmatrix = *matrix;
5401 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5402 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5403 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5404 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5406 switch(vid.renderpath)
5408 case RENDERPATH_D3D9:
5410 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5411 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5414 case RENDERPATH_D3D10:
5415 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5417 case RENDERPATH_D3D11:
5418 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5420 case RENDERPATH_GL11:
5421 case RENDERPATH_GL13:
5422 case RENDERPATH_GLES1:
5423 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5425 case RENDERPATH_SOFT:
5426 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5427 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5429 case RENDERPATH_GL20:
5430 case RENDERPATH_GLES2:
5431 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5432 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5438 void R_ResetViewRendering2D(void)
5440 r_viewport_t viewport;
5443 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5444 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);
5445 R_Mesh_ResetRenderTargets();
5446 R_SetViewport(&viewport);
5447 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5448 GL_Color(1, 1, 1, 1);
5449 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5450 GL_BlendFunc(GL_ONE, GL_ZERO);
5451 GL_ScissorTest(false);
5452 GL_DepthMask(false);
5453 GL_DepthRange(0, 1);
5454 GL_DepthTest(false);
5455 GL_DepthFunc(GL_LEQUAL);
5456 R_EntityMatrix(&identitymatrix);
5457 R_Mesh_ResetTextureState();
5458 GL_PolygonOffset(0, 0);
5459 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5460 switch(vid.renderpath)
5462 case RENDERPATH_GL11:
5463 case RENDERPATH_GL13:
5464 case RENDERPATH_GL20:
5465 case RENDERPATH_GLES1:
5466 case RENDERPATH_GLES2:
5467 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5469 case RENDERPATH_D3D9:
5470 case RENDERPATH_D3D10:
5471 case RENDERPATH_D3D11:
5472 case RENDERPATH_SOFT:
5475 GL_CullFace(GL_NONE);
5478 void R_ResetViewRendering3D(void)
5483 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5484 GL_Color(1, 1, 1, 1);
5485 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5486 GL_BlendFunc(GL_ONE, GL_ZERO);
5487 GL_ScissorTest(true);
5489 GL_DepthRange(0, 1);
5491 GL_DepthFunc(GL_LEQUAL);
5492 R_EntityMatrix(&identitymatrix);
5493 R_Mesh_ResetTextureState();
5494 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5495 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5496 switch(vid.renderpath)
5498 case RENDERPATH_GL11:
5499 case RENDERPATH_GL13:
5500 case RENDERPATH_GL20:
5501 case RENDERPATH_GLES1:
5502 case RENDERPATH_GLES2:
5503 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5505 case RENDERPATH_D3D9:
5506 case RENDERPATH_D3D10:
5507 case RENDERPATH_D3D11:
5508 case RENDERPATH_SOFT:
5511 GL_CullFace(r_refdef.view.cullface_back);
5516 R_RenderView_UpdateViewVectors
5519 static void R_RenderView_UpdateViewVectors(void)
5521 // break apart the view matrix into vectors for various purposes
5522 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5523 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5524 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5525 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5526 // make an inverted copy of the view matrix for tracking sprites
5527 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5530 void R_RenderScene(void);
5531 void R_RenderWaterPlanes(void);
5533 static void R_Water_StartFrame(void)
5536 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5537 r_waterstate_waterplane_t *p;
5539 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5542 switch(vid.renderpath)
5544 case RENDERPATH_GL20:
5545 case RENDERPATH_D3D9:
5546 case RENDERPATH_D3D10:
5547 case RENDERPATH_D3D11:
5548 case RENDERPATH_SOFT:
5549 case RENDERPATH_GLES2:
5551 case RENDERPATH_GL11:
5552 case RENDERPATH_GL13:
5553 case RENDERPATH_GLES1:
5557 // set waterwidth and waterheight to the water resolution that will be
5558 // used (often less than the screen resolution for faster rendering)
5559 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5561 // calculate desired texture sizes
5562 // can't use water if the card does not support the texture size
5563 if (!r_water.integer || r_showsurfaces.integer)
5564 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5565 else if (vid.support.arb_texture_non_power_of_two)
5567 texturewidth = waterwidth;
5568 textureheight = waterheight;
5569 camerawidth = waterwidth;
5570 cameraheight = waterheight;
5574 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5575 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5576 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5577 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5580 // allocate textures as needed
5581 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5583 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5584 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5586 if (p->texture_refraction)
5587 R_FreeTexture(p->texture_refraction);
5588 p->texture_refraction = NULL;
5589 if (p->texture_reflection)
5590 R_FreeTexture(p->texture_reflection);
5591 p->texture_reflection = NULL;
5592 if (p->texture_camera)
5593 R_FreeTexture(p->texture_camera);
5594 p->texture_camera = NULL;
5596 memset(&r_waterstate, 0, sizeof(r_waterstate));
5597 r_waterstate.texturewidth = texturewidth;
5598 r_waterstate.textureheight = textureheight;
5599 r_waterstate.camerawidth = camerawidth;
5600 r_waterstate.cameraheight = cameraheight;
5603 if (r_waterstate.texturewidth)
5605 int scaledwidth, scaledheight;
5607 r_waterstate.enabled = true;
5609 // when doing a reduced render (HDR) we want to use a smaller area
5610 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5611 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5612 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5614 // set up variables that will be used in shader setup
5615 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5616 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5617 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5618 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5621 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5622 r_waterstate.numwaterplanes = 0;
5625 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5627 int triangleindex, planeindex;
5633 r_waterstate_waterplane_t *p;
5634 texture_t *t = R_GetCurrentTexture(surface->texture);
5636 // just use the first triangle with a valid normal for any decisions
5637 VectorClear(normal);
5638 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5640 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5641 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5642 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5643 TriangleNormal(vert[0], vert[1], vert[2], normal);
5644 if (VectorLength2(normal) >= 0.001)
5648 VectorCopy(normal, plane.normal);
5649 VectorNormalize(plane.normal);
5650 plane.dist = DotProduct(vert[0], plane.normal);
5651 PlaneClassify(&plane);
5652 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5654 // skip backfaces (except if nocullface is set)
5655 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5657 VectorNegate(plane.normal, plane.normal);
5659 PlaneClassify(&plane);
5663 // find a matching plane if there is one
5664 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5665 if(p->camera_entity == t->camera_entity)
5666 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5668 if (planeindex >= r_waterstate.maxwaterplanes)
5669 return; // nothing we can do, out of planes
5671 // if this triangle does not fit any known plane rendered this frame, add one
5672 if (planeindex >= r_waterstate.numwaterplanes)
5674 // store the new plane
5675 r_waterstate.numwaterplanes++;
5677 // clear materialflags and pvs
5678 p->materialflags = 0;
5679 p->pvsvalid = false;
5680 p->camera_entity = t->camera_entity;
5681 VectorCopy(surface->mins, p->mins);
5682 VectorCopy(surface->maxs, p->maxs);
5687 p->mins[0] = min(p->mins[0], surface->mins[0]);
5688 p->mins[1] = min(p->mins[1], surface->mins[1]);
5689 p->mins[2] = min(p->mins[2], surface->mins[2]);
5690 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5691 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5692 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5694 // merge this surface's materialflags into the waterplane
5695 p->materialflags |= t->currentmaterialflags;
5696 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5698 // merge this surface's PVS into the waterplane
5699 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5700 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5701 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5703 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5709 extern cvar_t r_drawparticles;
5710 extern cvar_t r_drawdecals;
5712 static void R_Water_ProcessPlanes(void)
5715 r_refdef_view_t originalview;
5716 r_refdef_view_t myview;
5717 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;
5718 r_waterstate_waterplane_t *p;
5721 originalview = r_refdef.view;
5723 // lowquality hack, temporarily shut down some cvars and restore afterwards
5724 qualityreduction = r_water_lowquality.integer;
5725 if (qualityreduction > 0)
5727 if (qualityreduction >= 1)
5729 old_r_shadows = r_shadows.integer;
5730 old_r_worldrtlight = r_shadow_realtime_world.integer;
5731 old_r_dlight = r_shadow_realtime_dlight.integer;
5732 Cvar_SetValueQuick(&r_shadows, 0);
5733 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5734 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5736 if (qualityreduction >= 2)
5738 old_r_dynamic = r_dynamic.integer;
5739 old_r_particles = r_drawparticles.integer;
5740 old_r_decals = r_drawdecals.integer;
5741 Cvar_SetValueQuick(&r_dynamic, 0);
5742 Cvar_SetValueQuick(&r_drawparticles, 0);
5743 Cvar_SetValueQuick(&r_drawdecals, 0);
5747 // make sure enough textures are allocated
5748 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5750 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5752 if (!p->texture_refraction)
5753 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);
5754 if (!p->texture_refraction)
5757 else if (p->materialflags & MATERIALFLAG_CAMERA)
5759 if (!p->texture_camera)
5760 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);
5761 if (!p->texture_camera)
5765 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5767 if (!p->texture_reflection)
5768 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);
5769 if (!p->texture_reflection)
5775 r_refdef.view = originalview;
5776 r_refdef.view.showdebug = false;
5777 r_refdef.view.width = r_waterstate.waterwidth;
5778 r_refdef.view.height = r_waterstate.waterheight;
5779 r_refdef.view.useclipplane = true;
5780 myview = r_refdef.view;
5781 r_waterstate.renderingscene = true;
5782 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5784 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5786 r_refdef.view = myview;
5787 if(r_water_scissormode.integer)
5790 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5791 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5794 // render reflected scene and copy into texture
5795 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5796 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5797 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5798 r_refdef.view.clipplane = p->plane;
5799 // reverse the cullface settings for this render
5800 r_refdef.view.cullface_front = GL_FRONT;
5801 r_refdef.view.cullface_back = GL_BACK;
5802 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5804 r_refdef.view.usecustompvs = true;
5806 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5808 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5811 R_ResetViewRendering3D();
5812 R_ClearScreen(r_refdef.fogenabled);
5813 if(r_water_scissormode.integer & 2)
5814 R_View_UpdateWithScissor(myscissor);
5817 if(r_water_scissormode.integer & 1)
5818 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5821 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);
5824 // render the normal view scene and copy into texture
5825 // (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)
5826 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5828 r_refdef.view = myview;
5829 if(r_water_scissormode.integer)
5832 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5833 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5836 r_waterstate.renderingrefraction = true;
5838 r_refdef.view.clipplane = p->plane;
5839 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5840 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5842 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5844 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5845 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5846 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5847 R_RenderView_UpdateViewVectors();
5848 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5850 r_refdef.view.usecustompvs = true;
5851 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);
5855 PlaneClassify(&r_refdef.view.clipplane);
5857 R_ResetViewRendering3D();
5858 R_ClearScreen(r_refdef.fogenabled);
5859 if(r_water_scissormode.integer & 2)
5860 R_View_UpdateWithScissor(myscissor);
5863 if(r_water_scissormode.integer & 1)
5864 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5867 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);
5868 r_waterstate.renderingrefraction = false;
5870 else if (p->materialflags & MATERIALFLAG_CAMERA)
5872 r_refdef.view = myview;
5874 r_refdef.view.clipplane = p->plane;
5875 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5876 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5878 r_refdef.view.width = r_waterstate.camerawidth;
5879 r_refdef.view.height = r_waterstate.cameraheight;
5880 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5881 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5883 if(p->camera_entity)
5885 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5886 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5889 // note: all of the view is used for displaying... so
5890 // there is no use in scissoring
5892 // reverse the cullface settings for this render
5893 r_refdef.view.cullface_front = GL_FRONT;
5894 r_refdef.view.cullface_back = GL_BACK;
5895 // also reverse the view matrix
5896 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
5897 R_RenderView_UpdateViewVectors();
5898 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5900 r_refdef.view.usecustompvs = true;
5901 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);
5904 // camera needs no clipplane
5905 r_refdef.view.useclipplane = false;
5907 PlaneClassify(&r_refdef.view.clipplane);
5909 R_ResetViewRendering3D();
5910 R_ClearScreen(r_refdef.fogenabled);
5914 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);
5915 r_waterstate.renderingrefraction = false;
5919 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5920 r_waterstate.renderingscene = false;
5921 r_refdef.view = originalview;
5922 R_ResetViewRendering3D();
5923 R_ClearScreen(r_refdef.fogenabled);
5927 r_refdef.view = originalview;
5928 r_waterstate.renderingscene = false;
5929 Cvar_SetValueQuick(&r_water, 0);
5930 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5932 // lowquality hack, restore cvars
5933 if (qualityreduction > 0)
5935 if (qualityreduction >= 1)
5937 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5938 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5939 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5941 if (qualityreduction >= 2)
5943 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5944 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5945 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5950 void R_Bloom_StartFrame(void)
5952 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5953 int viewwidth, viewheight;
5956 if (r_viewscale_fpsscaling.integer)
5958 double actualframetime;
5959 double targetframetime;
5961 actualframetime = r_refdef.lastdrawscreentime;
5962 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5963 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5964 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5965 if (r_viewscale_fpsscaling_stepsize.value > 0)
5966 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5967 viewscalefpsadjusted += adjust;
5968 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5971 viewscalefpsadjusted = 1.0f;
5973 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5975 switch(vid.renderpath)
5977 case RENDERPATH_GL20:
5978 case RENDERPATH_D3D9:
5979 case RENDERPATH_D3D10:
5980 case RENDERPATH_D3D11:
5981 case RENDERPATH_SOFT:
5982 case RENDERPATH_GLES2:
5984 case RENDERPATH_GL11:
5985 case RENDERPATH_GL13:
5986 case RENDERPATH_GLES1:
5990 // set bloomwidth and bloomheight to the bloom resolution that will be
5991 // used (often less than the screen resolution for faster rendering)
5992 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5993 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5994 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5995 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5996 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5998 // calculate desired texture sizes
5999 if (vid.support.arb_texture_non_power_of_two)
6001 screentexturewidth = vid.width;
6002 screentextureheight = vid.height;
6003 bloomtexturewidth = r_bloomstate.bloomwidth;
6004 bloomtextureheight = r_bloomstate.bloomheight;
6008 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6009 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6010 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
6011 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
6014 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))
6016 Cvar_SetValueQuick(&r_hdr, 0);
6017 Cvar_SetValueQuick(&r_bloom, 0);
6018 Cvar_SetValueQuick(&r_motionblur, 0);
6019 Cvar_SetValueQuick(&r_damageblur, 0);
6022 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)
6023 screentexturewidth = screentextureheight = 0;
6024 if (!r_hdr.integer && !r_bloom.integer)
6025 bloomtexturewidth = bloomtextureheight = 0;
6027 textype = TEXTYPE_COLORBUFFER;
6028 switch (vid.renderpath)
6030 case RENDERPATH_GL20:
6031 case RENDERPATH_GLES2:
6032 if (vid.support.ext_framebuffer_object)
6034 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6035 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6038 case RENDERPATH_GL11:
6039 case RENDERPATH_GL13:
6040 case RENDERPATH_GLES1:
6041 case RENDERPATH_D3D9:
6042 case RENDERPATH_D3D10:
6043 case RENDERPATH_D3D11:
6044 case RENDERPATH_SOFT:
6048 // allocate textures as needed
6049 if (r_bloomstate.screentexturewidth != screentexturewidth
6050 || r_bloomstate.screentextureheight != screentextureheight
6051 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6052 || r_bloomstate.bloomtextureheight != bloomtextureheight
6053 || r_bloomstate.texturetype != textype
6054 || r_bloomstate.viewfbo != r_viewfbo.integer)
6056 if (r_bloomstate.texture_bloom)
6057 R_FreeTexture(r_bloomstate.texture_bloom);
6058 r_bloomstate.texture_bloom = NULL;
6059 if (r_bloomstate.texture_screen)
6060 R_FreeTexture(r_bloomstate.texture_screen);
6061 r_bloomstate.texture_screen = NULL;
6062 if (r_bloomstate.fbo_framebuffer)
6063 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6064 r_bloomstate.fbo_framebuffer = 0;
6065 if (r_bloomstate.texture_framebuffercolor)
6066 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6067 r_bloomstate.texture_framebuffercolor = NULL;
6068 if (r_bloomstate.texture_framebufferdepth)
6069 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6070 r_bloomstate.texture_framebufferdepth = NULL;
6071 r_bloomstate.screentexturewidth = screentexturewidth;
6072 r_bloomstate.screentextureheight = screentextureheight;
6073 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6074 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);
6075 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6077 // FIXME: choose depth bits based on a cvar
6078 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6079 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);
6080 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6081 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6083 // render depth into one texture and normalmap into the other
6087 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6088 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6089 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6090 if (status != GL_FRAMEBUFFER_COMPLETE)
6091 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6095 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6096 r_bloomstate.bloomtextureheight = bloomtextureheight;
6097 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6098 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);
6099 r_bloomstate.viewfbo = r_viewfbo.integer;
6100 r_bloomstate.texturetype = textype;
6103 // when doing a reduced render (HDR) we want to use a smaller area
6104 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6105 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6106 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6107 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6108 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6110 // set up a texcoord array for the full resolution screen image
6111 // (we have to keep this around to copy back during final render)
6112 r_bloomstate.screentexcoord2f[0] = 0;
6113 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6114 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6115 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6116 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6117 r_bloomstate.screentexcoord2f[5] = 0;
6118 r_bloomstate.screentexcoord2f[6] = 0;
6119 r_bloomstate.screentexcoord2f[7] = 0;
6121 // set up a texcoord array for the reduced resolution bloom image
6122 // (which will be additive blended over the screen image)
6123 r_bloomstate.bloomtexcoord2f[0] = 0;
6124 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6125 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6126 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6127 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6128 r_bloomstate.bloomtexcoord2f[5] = 0;
6129 r_bloomstate.bloomtexcoord2f[6] = 0;
6130 r_bloomstate.bloomtexcoord2f[7] = 0;
6132 switch(vid.renderpath)
6134 case RENDERPATH_GL11:
6135 case RENDERPATH_GL13:
6136 case RENDERPATH_GL20:
6137 case RENDERPATH_SOFT:
6138 case RENDERPATH_GLES1:
6139 case RENDERPATH_GLES2:
6141 case RENDERPATH_D3D9:
6142 case RENDERPATH_D3D10:
6143 case RENDERPATH_D3D11:
6146 for (i = 0;i < 4;i++)
6148 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6149 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6150 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6151 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6157 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6159 r_bloomstate.enabled = true;
6160 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6163 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);
6165 if (r_bloomstate.fbo_framebuffer)
6166 r_refdef.view.clear = true;
6169 void R_Bloom_CopyBloomTexture(float colorscale)
6171 r_refdef.stats.bloom++;
6173 // scale down screen texture to the bloom texture size
6175 R_Mesh_SetMainRenderTargets();
6176 R_SetViewport(&r_bloomstate.viewport);
6177 GL_BlendFunc(GL_ONE, GL_ZERO);
6178 GL_Color(colorscale, colorscale, colorscale, 1);
6179 // 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...
6180 switch(vid.renderpath)
6182 case RENDERPATH_GL11:
6183 case RENDERPATH_GL13:
6184 case RENDERPATH_GL20:
6185 case RENDERPATH_GLES1:
6186 case RENDERPATH_GLES2:
6187 case RENDERPATH_SOFT:
6188 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6190 case RENDERPATH_D3D9:
6191 case RENDERPATH_D3D10:
6192 case RENDERPATH_D3D11:
6193 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6196 // TODO: do boxfilter scale-down in shader?
6197 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6198 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6199 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6201 // we now have a bloom image in the framebuffer
6202 // copy it into the bloom image texture for later processing
6203 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);
6204 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6207 void R_Bloom_CopyHDRTexture(void)
6209 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);
6210 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6213 void R_Bloom_MakeTexture(void)
6216 float xoffset, yoffset, r, brighten;
6218 r_refdef.stats.bloom++;
6220 R_ResetViewRendering2D();
6222 // we have a bloom image in the framebuffer
6224 R_SetViewport(&r_bloomstate.viewport);
6226 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6229 r = bound(0, r_bloom_colorexponent.value / x, 1);
6230 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6232 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6233 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6234 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6235 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6237 // copy the vertically blurred bloom view to a texture
6238 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);
6239 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6242 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6243 brighten = r_bloom_brighten.value;
6244 if (r_bloomstate.hdr)
6245 brighten *= r_hdr_range.value;
6246 brighten = sqrt(brighten);
6248 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6249 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6251 for (dir = 0;dir < 2;dir++)
6253 // blend on at multiple vertical offsets to achieve a vertical blur
6254 // TODO: do offset blends using GLSL
6255 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6256 GL_BlendFunc(GL_ONE, GL_ZERO);
6257 for (x = -range;x <= range;x++)
6259 if (!dir){xoffset = 0;yoffset = x;}
6260 else {xoffset = x;yoffset = 0;}
6261 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6262 yoffset /= (float)r_bloomstate.bloomtextureheight;
6263 // compute a texcoord array with the specified x and y offset
6264 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6265 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6266 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6267 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6268 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6269 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6270 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6271 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6272 // this r value looks like a 'dot' particle, fading sharply to
6273 // black at the edges
6274 // (probably not realistic but looks good enough)
6275 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6276 //r = brighten/(range*2+1);
6277 r = brighten / (range * 2 + 1);
6279 r *= (1 - x*x/(float)(range*range));
6280 GL_Color(r, r, r, 1);
6281 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6282 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6283 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6284 GL_BlendFunc(GL_ONE, GL_ONE);
6287 // copy the vertically blurred bloom view to a texture
6288 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);
6289 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6293 void R_HDR_RenderBloomTexture(void)
6295 int oldwidth, oldheight;
6296 float oldcolorscale;
6297 qboolean oldwaterstate;
6299 oldwaterstate = r_waterstate.enabled;
6300 oldcolorscale = r_refdef.view.colorscale;
6301 oldwidth = r_refdef.view.width;
6302 oldheight = r_refdef.view.height;
6303 r_refdef.view.width = r_bloomstate.bloomwidth;
6304 r_refdef.view.height = r_bloomstate.bloomheight;
6306 if(r_hdr.integer < 2)
6307 r_waterstate.enabled = false;
6309 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6310 // TODO: add exposure compensation features
6311 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6313 r_refdef.view.showdebug = false;
6314 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6316 R_ResetViewRendering3D();
6318 R_ClearScreen(r_refdef.fogenabled);
6319 if (r_timereport_active)
6320 R_TimeReport("HDRclear");
6323 if (r_timereport_active)
6324 R_TimeReport("visibility");
6326 // only do secondary renders with HDR if r_hdr is 2 or higher
6327 r_waterstate.numwaterplanes = 0;
6328 if (r_waterstate.enabled)
6329 R_RenderWaterPlanes();
6331 r_refdef.view.showdebug = true;
6333 r_waterstate.numwaterplanes = 0;
6335 R_ResetViewRendering2D();
6337 R_Bloom_CopyHDRTexture();
6338 R_Bloom_MakeTexture();
6340 // restore the view settings
6341 r_waterstate.enabled = oldwaterstate;
6342 r_refdef.view.width = oldwidth;
6343 r_refdef.view.height = oldheight;
6344 r_refdef.view.colorscale = oldcolorscale;
6346 R_ResetViewRendering3D();
6348 R_ClearScreen(r_refdef.fogenabled);
6349 if (r_timereport_active)
6350 R_TimeReport("viewclear");
6353 static void R_BlendView(void)
6355 unsigned int permutation;
6356 float uservecs[4][4];
6358 switch (vid.renderpath)
6360 case RENDERPATH_GL20:
6361 case RENDERPATH_D3D9:
6362 case RENDERPATH_D3D10:
6363 case RENDERPATH_D3D11:
6364 case RENDERPATH_SOFT:
6365 case RENDERPATH_GLES2:
6367 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6368 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6369 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6370 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6371 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6373 if (r_bloomstate.texture_screen)
6375 // make sure the buffer is available
6376 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6378 R_ResetViewRendering2D();
6379 R_Mesh_SetMainRenderTargets();
6381 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6383 // declare variables
6384 float blur_factor, blur_mouseaccel, blur_velocity;
6385 static float blur_average;
6386 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6388 // set a goal for the factoring
6389 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6390 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6391 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6392 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6393 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6394 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6396 // from the goal, pick an averaged value between goal and last value
6397 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6398 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6400 // enforce minimum amount of blur
6401 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6403 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6405 // calculate values into a standard alpha
6406 cl.motionbluralpha = 1 - exp(-
6408 (r_motionblur.value * blur_factor / 80)
6410 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6413 max(0.0001, cl.time - cl.oldtime) // fps independent
6416 // randomization for the blur value to combat persistent ghosting
6417 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6418 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6421 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6423 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6424 GL_Color(1, 1, 1, cl.motionbluralpha);
6425 switch(vid.renderpath)
6427 case RENDERPATH_GL11:
6428 case RENDERPATH_GL13:
6429 case RENDERPATH_GL20:
6430 case RENDERPATH_GLES1:
6431 case RENDERPATH_GLES2:
6432 case RENDERPATH_SOFT:
6433 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6435 case RENDERPATH_D3D9:
6436 case RENDERPATH_D3D10:
6437 case RENDERPATH_D3D11:
6438 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6441 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6442 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6443 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6446 // updates old view angles for next pass
6447 VectorCopy(cl.viewangles, blur_oldangles);
6450 // copy view into the screen texture
6451 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);
6452 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6454 else if (!r_bloomstate.texture_bloom)
6456 // we may still have to do view tint...
6457 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6459 // apply a color tint to the whole view
6460 R_ResetViewRendering2D();
6461 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6462 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6463 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6464 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6465 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6467 break; // no screen processing, no bloom, skip it
6470 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6472 // render simple bloom effect
6473 // copy the screen and shrink it and darken it for the bloom process
6474 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6475 // make the bloom texture
6476 R_Bloom_MakeTexture();
6479 #if _MSC_VER >= 1400
6480 #define sscanf sscanf_s
6482 memset(uservecs, 0, sizeof(uservecs));
6483 if (r_glsl_postprocess_uservec1_enable.integer)
6484 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6485 if (r_glsl_postprocess_uservec2_enable.integer)
6486 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6487 if (r_glsl_postprocess_uservec3_enable.integer)
6488 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6489 if (r_glsl_postprocess_uservec4_enable.integer)
6490 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6492 R_ResetViewRendering2D();
6493 GL_Color(1, 1, 1, 1);
6494 GL_BlendFunc(GL_ONE, GL_ZERO);
6496 switch(vid.renderpath)
6498 case RENDERPATH_GL20:
6499 case RENDERPATH_GLES2:
6500 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6501 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6502 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6503 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6504 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6505 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]);
6506 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6507 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]);
6508 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]);
6509 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]);
6510 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]);
6511 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6512 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6513 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);
6515 case RENDERPATH_D3D9:
6517 // 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...
6518 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6519 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6520 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6521 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6522 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6523 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6524 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6525 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6526 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6527 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6528 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6529 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6530 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6531 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6534 case RENDERPATH_D3D10:
6535 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6537 case RENDERPATH_D3D11:
6538 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6540 case RENDERPATH_SOFT:
6541 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6542 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6543 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6544 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6545 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6546 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6547 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6548 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6549 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6550 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6551 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6552 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6553 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6554 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6559 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6560 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6562 case RENDERPATH_GL11:
6563 case RENDERPATH_GL13:
6564 case RENDERPATH_GLES1:
6565 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6567 // apply a color tint to the whole view
6568 R_ResetViewRendering2D();
6569 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6570 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6571 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6572 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6573 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6579 matrix4x4_t r_waterscrollmatrix;
6581 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6583 if (r_refdef.fog_density)
6585 r_refdef.fogcolor[0] = r_refdef.fog_red;
6586 r_refdef.fogcolor[1] = r_refdef.fog_green;
6587 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6589 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6590 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6591 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6592 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6596 VectorCopy(r_refdef.fogcolor, fogvec);
6597 // color.rgb *= ContrastBoost * SceneBrightness;
6598 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6599 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6600 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6601 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6606 void R_UpdateVariables(void)
6610 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6612 r_refdef.farclip = r_farclip_base.value;
6613 if (r_refdef.scene.worldmodel)
6614 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6615 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6617 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6618 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6619 r_refdef.polygonfactor = 0;
6620 r_refdef.polygonoffset = 0;
6621 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6622 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6624 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6625 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6626 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6627 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6628 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6629 if (FAKELIGHT_ENABLED)
6631 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6633 if (r_showsurfaces.integer)
6635 r_refdef.scene.rtworld = false;
6636 r_refdef.scene.rtworldshadows = false;
6637 r_refdef.scene.rtdlight = false;
6638 r_refdef.scene.rtdlightshadows = false;
6639 r_refdef.lightmapintensity = 0;
6642 if (gamemode == GAME_NEHAHRA)
6644 if (gl_fogenable.integer)
6646 r_refdef.oldgl_fogenable = true;
6647 r_refdef.fog_density = gl_fogdensity.value;
6648 r_refdef.fog_red = gl_fogred.value;
6649 r_refdef.fog_green = gl_foggreen.value;
6650 r_refdef.fog_blue = gl_fogblue.value;
6651 r_refdef.fog_alpha = 1;
6652 r_refdef.fog_start = 0;
6653 r_refdef.fog_end = gl_skyclip.value;
6654 r_refdef.fog_height = 1<<30;
6655 r_refdef.fog_fadedepth = 128;
6657 else if (r_refdef.oldgl_fogenable)
6659 r_refdef.oldgl_fogenable = false;
6660 r_refdef.fog_density = 0;
6661 r_refdef.fog_red = 0;
6662 r_refdef.fog_green = 0;
6663 r_refdef.fog_blue = 0;
6664 r_refdef.fog_alpha = 0;
6665 r_refdef.fog_start = 0;
6666 r_refdef.fog_end = 0;
6667 r_refdef.fog_height = 1<<30;
6668 r_refdef.fog_fadedepth = 128;
6672 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6673 r_refdef.fog_start = max(0, r_refdef.fog_start);
6674 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6676 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6678 if (r_refdef.fog_density && r_drawfog.integer)
6680 r_refdef.fogenabled = true;
6681 // this is the point where the fog reaches 0.9986 alpha, which we
6682 // consider a good enough cutoff point for the texture
6683 // (0.9986 * 256 == 255.6)
6684 if (r_fog_exp2.integer)
6685 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6687 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6688 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6689 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6690 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6691 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6692 R_BuildFogHeightTexture();
6693 // fog color was already set
6694 // update the fog texture
6695 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)
6696 R_BuildFogTexture();
6697 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6698 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6701 r_refdef.fogenabled = false;
6703 switch(vid.renderpath)
6705 case RENDERPATH_GL20:
6706 case RENDERPATH_D3D9:
6707 case RENDERPATH_D3D10:
6708 case RENDERPATH_D3D11:
6709 case RENDERPATH_SOFT:
6710 case RENDERPATH_GLES2:
6711 if(v_glslgamma.integer && !vid_gammatables_trivial)
6713 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6715 // build GLSL gamma texture
6716 #define RAMPWIDTH 256
6717 unsigned short ramp[RAMPWIDTH * 3];
6718 unsigned char rampbgr[RAMPWIDTH][4];
6721 r_texture_gammaramps_serial = vid_gammatables_serial;
6723 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6724 for(i = 0; i < RAMPWIDTH; ++i)
6726 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6727 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6728 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6731 if (r_texture_gammaramps)
6733 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6737 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6743 // remove GLSL gamma texture
6746 case RENDERPATH_GL11:
6747 case RENDERPATH_GL13:
6748 case RENDERPATH_GLES1:
6753 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6754 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6760 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6761 if( scenetype != r_currentscenetype ) {
6762 // store the old scenetype
6763 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6764 r_currentscenetype = scenetype;
6765 // move in the new scene
6766 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6775 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6777 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6778 if( scenetype == r_currentscenetype ) {
6779 return &r_refdef.scene;
6781 return &r_scenes_store[ scenetype ];
6785 int R_SortEntities_Compare(const void *ap, const void *bp)
6787 const entity_render_t *a = *(const entity_render_t **)ap;
6788 const entity_render_t *b = *(const entity_render_t **)bp;
6791 if(a->model < b->model)
6793 if(a->model > b->model)
6797 // TODO possibly calculate the REAL skinnum here first using
6799 if(a->skinnum < b->skinnum)
6801 if(a->skinnum > b->skinnum)
6804 // everything we compared is equal
6807 void R_SortEntities(void)
6809 // below or equal 2 ents, sorting never gains anything
6810 if(r_refdef.scene.numentities <= 2)
6813 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6821 int dpsoftrast_test;
6822 extern void R_Shadow_UpdateBounceGridTexture(void);
6823 extern cvar_t r_shadow_bouncegrid;
6824 void R_RenderView(void)
6826 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6828 dpsoftrast_test = r_test.integer;
6830 if (r_timereport_active)
6831 R_TimeReport("start");
6832 r_textureframe++; // used only by R_GetCurrentTexture
6833 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6835 if(R_CompileShader_CheckStaticParms())
6838 if (!r_drawentities.integer)
6839 r_refdef.scene.numentities = 0;
6840 else if (r_sortentities.integer)
6843 R_AnimCache_ClearCache();
6844 R_FrameData_NewFrame();
6846 /* adjust for stereo display */
6847 if(R_Stereo_Active())
6849 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);
6850 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6853 if (r_refdef.view.isoverlay)
6855 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6856 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6857 R_TimeReport("depthclear");
6859 r_refdef.view.showdebug = false;
6861 r_waterstate.enabled = false;
6862 r_waterstate.numwaterplanes = 0;
6866 r_refdef.view.matrix = originalmatrix;
6872 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6874 r_refdef.view.matrix = originalmatrix;
6875 return; //Host_Error ("R_RenderView: NULL worldmodel");
6878 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6880 R_RenderView_UpdateViewVectors();
6882 R_Shadow_UpdateWorldLightSelection();
6884 R_Bloom_StartFrame();
6885 R_Water_StartFrame();
6888 if (r_timereport_active)
6889 R_TimeReport("viewsetup");
6891 R_ResetViewRendering3D();
6893 if (r_refdef.view.clear || r_refdef.fogenabled)
6895 R_ClearScreen(r_refdef.fogenabled);
6896 if (r_timereport_active)
6897 R_TimeReport("viewclear");
6899 r_refdef.view.clear = true;
6901 // this produces a bloom texture to be used in R_BlendView() later
6902 if (r_bloomstate.hdr)
6904 R_HDR_RenderBloomTexture();
6905 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6906 r_textureframe++; // used only by R_GetCurrentTexture
6909 r_refdef.view.showdebug = true;
6912 if (r_timereport_active)
6913 R_TimeReport("visibility");
6915 R_Shadow_UpdateBounceGridTexture();
6916 if (r_timereport_active && r_shadow_bouncegrid.integer)
6917 R_TimeReport("bouncegrid");
6919 r_waterstate.numwaterplanes = 0;
6920 if (r_waterstate.enabled)
6921 R_RenderWaterPlanes();
6924 r_waterstate.numwaterplanes = 0;
6927 if (r_timereport_active)
6928 R_TimeReport("blendview");
6930 GL_Scissor(0, 0, vid.width, vid.height);
6931 GL_ScissorTest(false);
6933 r_refdef.view.matrix = originalmatrix;
6938 void R_RenderWaterPlanes(void)
6940 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6942 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6943 if (r_timereport_active)
6944 R_TimeReport("waterworld");
6947 // don't let sound skip if going slow
6948 if (r_refdef.scene.extraupdate)
6951 R_DrawModelsAddWaterPlanes();
6952 if (r_timereport_active)
6953 R_TimeReport("watermodels");
6955 if (r_waterstate.numwaterplanes)
6957 R_Water_ProcessPlanes();
6958 if (r_timereport_active)
6959 R_TimeReport("waterscenes");
6963 extern void R_DrawLightningBeams (void);
6964 extern void VM_CL_AddPolygonsToMeshQueue (void);
6965 extern void R_DrawPortals (void);
6966 extern cvar_t cl_locs_show;
6967 static void R_DrawLocs(void);
6968 static void R_DrawEntityBBoxes(void);
6969 static void R_DrawModelDecals(void);
6970 extern void R_DrawModelShadows(void);
6971 extern void R_DrawModelShadowMaps(void);
6972 extern cvar_t cl_decals_newsystem;
6973 extern qboolean r_shadow_usingdeferredprepass;
6974 void R_RenderScene(void)
6976 qboolean shadowmapping = false;
6978 if (r_timereport_active)
6979 R_TimeReport("beginscene");
6981 r_refdef.stats.renders++;
6985 // don't let sound skip if going slow
6986 if (r_refdef.scene.extraupdate)
6989 R_MeshQueue_BeginScene();
6993 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);
6995 if (r_timereport_active)
6996 R_TimeReport("skystartframe");
6998 if (cl.csqc_vidvars.drawworld)
7000 // don't let sound skip if going slow
7001 if (r_refdef.scene.extraupdate)
7004 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7006 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7007 if (r_timereport_active)
7008 R_TimeReport("worldsky");
7011 if (R_DrawBrushModelsSky() && r_timereport_active)
7012 R_TimeReport("bmodelsky");
7014 if (skyrendermasked && skyrenderlater)
7016 // we have to force off the water clipping plane while rendering sky
7020 if (r_timereport_active)
7021 R_TimeReport("sky");
7025 R_AnimCache_CacheVisibleEntities();
7026 if (r_timereport_active)
7027 R_TimeReport("animation");
7029 R_Shadow_PrepareLights();
7030 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7031 R_Shadow_PrepareModelShadows();
7032 if (r_timereport_active)
7033 R_TimeReport("preparelights");
7035 if (R_Shadow_ShadowMappingEnabled())
7036 shadowmapping = true;
7038 if (r_shadow_usingdeferredprepass)
7039 R_Shadow_DrawPrepass();
7041 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7043 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7044 if (r_timereport_active)
7045 R_TimeReport("worlddepth");
7047 if (r_depthfirst.integer >= 2)
7049 R_DrawModelsDepth();
7050 if (r_timereport_active)
7051 R_TimeReport("modeldepth");
7054 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7056 R_DrawModelShadowMaps();
7057 R_ResetViewRendering3D();
7058 // don't let sound skip if going slow
7059 if (r_refdef.scene.extraupdate)
7063 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7065 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7066 if (r_timereport_active)
7067 R_TimeReport("world");
7070 // don't let sound skip if going slow
7071 if (r_refdef.scene.extraupdate)
7075 if (r_timereport_active)
7076 R_TimeReport("models");
7078 // don't let sound skip if going slow
7079 if (r_refdef.scene.extraupdate)
7082 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7084 R_DrawModelShadows();
7085 R_ResetViewRendering3D();
7086 // don't let sound skip if going slow
7087 if (r_refdef.scene.extraupdate)
7091 if (!r_shadow_usingdeferredprepass)
7093 R_Shadow_DrawLights();
7094 if (r_timereport_active)
7095 R_TimeReport("rtlights");
7098 // don't let sound skip if going slow
7099 if (r_refdef.scene.extraupdate)
7102 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7104 R_DrawModelShadows();
7105 R_ResetViewRendering3D();
7106 // don't let sound skip if going slow
7107 if (r_refdef.scene.extraupdate)
7111 if (cl.csqc_vidvars.drawworld)
7113 if (cl_decals_newsystem.integer)
7115 R_DrawModelDecals();
7116 if (r_timereport_active)
7117 R_TimeReport("modeldecals");
7122 if (r_timereport_active)
7123 R_TimeReport("decals");
7127 if (r_timereport_active)
7128 R_TimeReport("particles");
7131 if (r_timereport_active)
7132 R_TimeReport("explosions");
7134 R_DrawLightningBeams();
7135 if (r_timereport_active)
7136 R_TimeReport("lightning");
7139 VM_CL_AddPolygonsToMeshQueue();
7141 if (r_refdef.view.showdebug)
7143 if (cl_locs_show.integer)
7146 if (r_timereport_active)
7147 R_TimeReport("showlocs");
7150 if (r_drawportals.integer)
7153 if (r_timereport_active)
7154 R_TimeReport("portals");
7157 if (r_showbboxes.value > 0)
7159 R_DrawEntityBBoxes();
7160 if (r_timereport_active)
7161 R_TimeReport("bboxes");
7165 if (r_transparent.integer)
7167 R_MeshQueue_RenderTransparent();
7168 if (r_timereport_active)
7169 R_TimeReport("drawtrans");
7172 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))
7174 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7175 if (r_timereport_active)
7176 R_TimeReport("worlddebug");
7177 R_DrawModelsDebug();
7178 if (r_timereport_active)
7179 R_TimeReport("modeldebug");
7182 if (cl.csqc_vidvars.drawworld)
7184 R_Shadow_DrawCoronas();
7185 if (r_timereport_active)
7186 R_TimeReport("coronas");
7191 GL_DepthTest(false);
7192 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7193 GL_Color(1, 1, 1, 1);
7194 qglBegin(GL_POLYGON);
7195 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7196 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7197 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7198 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7200 qglBegin(GL_POLYGON);
7201 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]);
7202 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]);
7203 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]);
7204 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]);
7206 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7210 // don't let sound skip if going slow
7211 if (r_refdef.scene.extraupdate)
7214 R_ResetViewRendering2D();
7217 static const unsigned short bboxelements[36] =
7227 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7230 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7232 RSurf_ActiveWorldEntity();
7234 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7235 GL_DepthMask(false);
7236 GL_DepthRange(0, 1);
7237 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7238 // R_Mesh_ResetTextureState();
7240 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7241 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7242 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7243 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7244 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7245 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7246 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7247 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7248 R_FillColors(color4f, 8, cr, cg, cb, ca);
7249 if (r_refdef.fogenabled)
7251 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7253 f1 = RSurf_FogVertex(v);
7255 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7256 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7257 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7260 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7261 R_Mesh_ResetTextureState();
7262 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7263 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7266 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7270 prvm_edict_t *edict;
7271 prvm_prog_t *prog_save = prog;
7273 // this function draws bounding boxes of server entities
7277 GL_CullFace(GL_NONE);
7278 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7282 for (i = 0;i < numsurfaces;i++)
7284 edict = PRVM_EDICT_NUM(surfacelist[i]);
7285 switch ((int)PRVM_serveredictfloat(edict, solid))
7287 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7288 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7289 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7290 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7291 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7292 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7294 color[3] *= r_showbboxes.value;
7295 color[3] = bound(0, color[3], 1);
7296 GL_DepthTest(!r_showdisabledepthtest.integer);
7297 GL_CullFace(r_refdef.view.cullface_front);
7298 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7304 static void R_DrawEntityBBoxes(void)
7307 prvm_edict_t *edict;
7309 prvm_prog_t *prog_save = prog;
7311 // this function draws bounding boxes of server entities
7317 for (i = 0;i < prog->num_edicts;i++)
7319 edict = PRVM_EDICT_NUM(i);
7320 if (edict->priv.server->free)
7322 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7323 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7325 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7327 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7328 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7334 static const int nomodelelement3i[24] =
7346 static const unsigned short nomodelelement3s[24] =
7358 static const float nomodelvertex3f[6*3] =
7368 static const float nomodelcolor4f[6*4] =
7370 0.0f, 0.0f, 0.5f, 1.0f,
7371 0.0f, 0.0f, 0.5f, 1.0f,
7372 0.0f, 0.5f, 0.0f, 1.0f,
7373 0.0f, 0.5f, 0.0f, 1.0f,
7374 0.5f, 0.0f, 0.0f, 1.0f,
7375 0.5f, 0.0f, 0.0f, 1.0f
7378 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7384 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);
7386 // this is only called once per entity so numsurfaces is always 1, and
7387 // surfacelist is always {0}, so this code does not handle batches
7389 if (rsurface.ent_flags & RENDER_ADDITIVE)
7391 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7392 GL_DepthMask(false);
7394 else if (rsurface.colormod[3] < 1)
7396 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7397 GL_DepthMask(false);
7401 GL_BlendFunc(GL_ONE, GL_ZERO);
7404 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7405 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7406 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7407 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7408 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7409 for (i = 0, c = color4f;i < 6;i++, c += 4)
7411 c[0] *= rsurface.colormod[0];
7412 c[1] *= rsurface.colormod[1];
7413 c[2] *= rsurface.colormod[2];
7414 c[3] *= rsurface.colormod[3];
7416 if (r_refdef.fogenabled)
7418 for (i = 0, c = color4f;i < 6;i++, c += 4)
7420 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7422 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7423 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7424 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7427 // R_Mesh_ResetTextureState();
7428 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7429 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7430 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7433 void R_DrawNoModel(entity_render_t *ent)
7436 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7437 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7438 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7440 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7443 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7445 vec3_t right1, right2, diff, normal;
7447 VectorSubtract (org2, org1, normal);
7449 // calculate 'right' vector for start
7450 VectorSubtract (r_refdef.view.origin, org1, diff);
7451 CrossProduct (normal, diff, right1);
7452 VectorNormalize (right1);
7454 // calculate 'right' vector for end
7455 VectorSubtract (r_refdef.view.origin, org2, diff);
7456 CrossProduct (normal, diff, right2);
7457 VectorNormalize (right2);
7459 vert[ 0] = org1[0] + width * right1[0];
7460 vert[ 1] = org1[1] + width * right1[1];
7461 vert[ 2] = org1[2] + width * right1[2];
7462 vert[ 3] = org1[0] - width * right1[0];
7463 vert[ 4] = org1[1] - width * right1[1];
7464 vert[ 5] = org1[2] - width * right1[2];
7465 vert[ 6] = org2[0] - width * right2[0];
7466 vert[ 7] = org2[1] - width * right2[1];
7467 vert[ 8] = org2[2] - width * right2[2];
7468 vert[ 9] = org2[0] + width * right2[0];
7469 vert[10] = org2[1] + width * right2[1];
7470 vert[11] = org2[2] + width * right2[2];
7473 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)
7475 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7476 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7477 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7478 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7479 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7480 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7481 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7482 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7483 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7484 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7485 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7486 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7489 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7494 VectorSet(v, x, y, z);
7495 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7496 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7498 if (i == mesh->numvertices)
7500 if (mesh->numvertices < mesh->maxvertices)
7502 VectorCopy(v, vertex3f);
7503 mesh->numvertices++;
7505 return mesh->numvertices;
7511 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7515 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7516 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7517 e = mesh->element3i + mesh->numtriangles * 3;
7518 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7520 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7521 if (mesh->numtriangles < mesh->maxtriangles)
7526 mesh->numtriangles++;
7528 element[1] = element[2];
7532 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7536 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7537 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7538 e = mesh->element3i + mesh->numtriangles * 3;
7539 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7541 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7542 if (mesh->numtriangles < mesh->maxtriangles)
7547 mesh->numtriangles++;
7549 element[1] = element[2];
7553 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7554 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7556 int planenum, planenum2;
7559 mplane_t *plane, *plane2;
7561 double temppoints[2][256*3];
7562 // figure out how large a bounding box we need to properly compute this brush
7564 for (w = 0;w < numplanes;w++)
7565 maxdist = max(maxdist, fabs(planes[w].dist));
7566 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7567 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7568 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7572 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7573 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7575 if (planenum2 == planenum)
7577 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);
7580 if (tempnumpoints < 3)
7582 // generate elements forming a triangle fan for this polygon
7583 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7587 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)
7589 texturelayer_t *layer;
7590 layer = t->currentlayers + t->currentnumlayers++;
7592 layer->depthmask = depthmask;
7593 layer->blendfunc1 = blendfunc1;
7594 layer->blendfunc2 = blendfunc2;
7595 layer->texture = texture;
7596 layer->texmatrix = *matrix;
7597 layer->color[0] = r;
7598 layer->color[1] = g;
7599 layer->color[2] = b;
7600 layer->color[3] = a;
7603 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7605 if(parms[0] == 0 && parms[1] == 0)
7607 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7608 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7613 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7616 index = parms[2] + rsurface.shadertime * parms[3];
7617 index -= floor(index);
7618 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7621 case Q3WAVEFUNC_NONE:
7622 case Q3WAVEFUNC_NOISE:
7623 case Q3WAVEFUNC_COUNT:
7626 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7627 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7628 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7629 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7630 case Q3WAVEFUNC_TRIANGLE:
7632 f = index - floor(index);
7645 f = parms[0] + parms[1] * f;
7646 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7647 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7651 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7657 matrix4x4_t matrix, temp;
7658 switch(tcmod->tcmod)
7662 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7663 matrix = r_waterscrollmatrix;
7665 matrix = identitymatrix;
7667 case Q3TCMOD_ENTITYTRANSLATE:
7668 // this is used in Q3 to allow the gamecode to control texcoord
7669 // scrolling on the entity, which is not supported in darkplaces yet.
7670 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7672 case Q3TCMOD_ROTATE:
7673 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7674 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7675 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7678 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7680 case Q3TCMOD_SCROLL:
7681 // extra care is needed because of precision breakdown with large values of time
7682 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7683 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7684 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7686 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7687 w = (int) tcmod->parms[0];
7688 h = (int) tcmod->parms[1];
7689 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7691 idx = (int) floor(f * w * h);
7692 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7694 case Q3TCMOD_STRETCH:
7695 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7696 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7698 case Q3TCMOD_TRANSFORM:
7699 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7700 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7701 VectorSet(tcmat + 6, 0 , 0 , 1);
7702 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7703 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7705 case Q3TCMOD_TURBULENT:
7706 // this is handled in the RSurf_PrepareVertices function
7707 matrix = identitymatrix;
7711 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7714 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7716 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7717 char name[MAX_QPATH];
7718 skinframe_t *skinframe;
7719 unsigned char pixels[296*194];
7720 strlcpy(cache->name, skinname, sizeof(cache->name));
7721 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7722 if (developer_loading.integer)
7723 Con_Printf("loading %s\n", name);
7724 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7725 if (!skinframe || !skinframe->base)
7728 fs_offset_t filesize;
7730 f = FS_LoadFile(name, tempmempool, true, &filesize);
7733 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7734 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7738 cache->skinframe = skinframe;
7741 texture_t *R_GetCurrentTexture(texture_t *t)
7744 const entity_render_t *ent = rsurface.entity;
7745 dp_model_t *model = ent->model;
7746 q3shaderinfo_layer_tcmod_t *tcmod;
7748 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7749 return t->currentframe;
7750 t->update_lastrenderframe = r_textureframe;
7751 t->update_lastrenderentity = (void *)ent;
7753 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7754 t->camera_entity = ent->entitynumber;
7756 t->camera_entity = 0;
7758 // switch to an alternate material if this is a q1bsp animated material
7760 texture_t *texture = t;
7761 int s = rsurface.ent_skinnum;
7762 if ((unsigned int)s >= (unsigned int)model->numskins)
7764 if (model->skinscenes)
7766 if (model->skinscenes[s].framecount > 1)
7767 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7769 s = model->skinscenes[s].firstframe;
7772 t = t + s * model->num_surfaces;
7775 // use an alternate animation if the entity's frame is not 0,
7776 // and only if the texture has an alternate animation
7777 if (rsurface.ent_alttextures && t->anim_total[1])
7778 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7780 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7782 texture->currentframe = t;
7785 // update currentskinframe to be a qw skin or animation frame
7786 if (rsurface.ent_qwskin >= 0)
7788 i = rsurface.ent_qwskin;
7789 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7791 r_qwskincache_size = cl.maxclients;
7793 Mem_Free(r_qwskincache);
7794 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7796 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7797 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7798 t->currentskinframe = r_qwskincache[i].skinframe;
7799 if (t->currentskinframe == NULL)
7800 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7802 else if (t->numskinframes >= 2)
7803 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7804 if (t->backgroundnumskinframes >= 2)
7805 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7807 t->currentmaterialflags = t->basematerialflags;
7808 t->currentalpha = rsurface.colormod[3];
7809 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7810 t->currentalpha *= r_wateralpha.value;
7811 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7812 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7813 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7814 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7815 if (!(rsurface.ent_flags & RENDER_LIGHT))
7816 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7817 else if (FAKELIGHT_ENABLED)
7819 // no modellight if using fakelight for the map
7821 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7823 // pick a model lighting mode
7824 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7825 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7827 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7829 if (rsurface.ent_flags & RENDER_ADDITIVE)
7830 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7831 else if (t->currentalpha < 1)
7832 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7833 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7834 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7835 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7836 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7837 if (t->backgroundnumskinframes)
7838 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7839 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7841 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7842 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7845 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7846 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7848 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7849 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7851 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7852 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7854 // there is no tcmod
7855 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7857 t->currenttexmatrix = r_waterscrollmatrix;
7858 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7860 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7862 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7863 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7866 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7867 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7868 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7869 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7871 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7872 if (t->currentskinframe->qpixels)
7873 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7874 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7875 if (!t->basetexture)
7876 t->basetexture = r_texture_notexture;
7877 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7878 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7879 t->nmaptexture = t->currentskinframe->nmap;
7880 if (!t->nmaptexture)
7881 t->nmaptexture = r_texture_blanknormalmap;
7882 t->glosstexture = r_texture_black;
7883 t->glowtexture = t->currentskinframe->glow;
7884 t->fogtexture = t->currentskinframe->fog;
7885 t->reflectmasktexture = t->currentskinframe->reflect;
7886 if (t->backgroundnumskinframes)
7888 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7889 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7890 t->backgroundglosstexture = r_texture_black;
7891 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7892 if (!t->backgroundnmaptexture)
7893 t->backgroundnmaptexture = r_texture_blanknormalmap;
7897 t->backgroundbasetexture = r_texture_white;
7898 t->backgroundnmaptexture = r_texture_blanknormalmap;
7899 t->backgroundglosstexture = r_texture_black;
7900 t->backgroundglowtexture = NULL;
7902 t->specularpower = r_shadow_glossexponent.value;
7903 // TODO: store reference values for these in the texture?
7904 t->specularscale = 0;
7905 if (r_shadow_gloss.integer > 0)
7907 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7909 if (r_shadow_glossintensity.value > 0)
7911 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7912 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7913 t->specularscale = r_shadow_glossintensity.value;
7916 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7918 t->glosstexture = r_texture_white;
7919 t->backgroundglosstexture = r_texture_white;
7920 t->specularscale = r_shadow_gloss2intensity.value;
7921 t->specularpower = r_shadow_gloss2exponent.value;
7924 t->specularscale *= t->specularscalemod;
7925 t->specularpower *= t->specularpowermod;
7926 t->rtlightambient = 0;
7928 // lightmaps mode looks bad with dlights using actual texturing, so turn
7929 // off the colormap and glossmap, but leave the normalmap on as it still
7930 // accurately represents the shading involved
7931 if (gl_lightmaps.integer)
7933 t->basetexture = r_texture_grey128;
7934 t->pantstexture = r_texture_black;
7935 t->shirttexture = r_texture_black;
7936 t->nmaptexture = r_texture_blanknormalmap;
7937 t->glosstexture = r_texture_black;
7938 t->glowtexture = NULL;
7939 t->fogtexture = NULL;
7940 t->reflectmasktexture = NULL;
7941 t->backgroundbasetexture = NULL;
7942 t->backgroundnmaptexture = r_texture_blanknormalmap;
7943 t->backgroundglosstexture = r_texture_black;
7944 t->backgroundglowtexture = NULL;
7945 t->specularscale = 0;
7946 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7949 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7950 VectorClear(t->dlightcolor);
7951 t->currentnumlayers = 0;
7952 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7954 int blendfunc1, blendfunc2;
7956 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7958 blendfunc1 = GL_SRC_ALPHA;
7959 blendfunc2 = GL_ONE;
7961 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7963 blendfunc1 = GL_SRC_ALPHA;
7964 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7966 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7968 blendfunc1 = t->customblendfunc[0];
7969 blendfunc2 = t->customblendfunc[1];
7973 blendfunc1 = GL_ONE;
7974 blendfunc2 = GL_ZERO;
7976 // don't colormod evilblend textures
7977 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7978 VectorSet(t->lightmapcolor, 1, 1, 1);
7979 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7980 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7982 // fullbright is not affected by r_refdef.lightmapintensity
7983 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]);
7984 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7985 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]);
7986 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7987 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]);
7991 vec3_t ambientcolor;
7993 // set the color tint used for lights affecting this surface
7994 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7996 // q3bsp has no lightmap updates, so the lightstylevalue that
7997 // would normally be baked into the lightmap must be
7998 // applied to the color
7999 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8000 if (model->type == mod_brushq3)
8001 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8002 colorscale *= r_refdef.lightmapintensity;
8003 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8004 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8005 // basic lit geometry
8006 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]);
8007 // add pants/shirt if needed
8008 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8009 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]);
8010 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8011 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]);
8012 // now add ambient passes if needed
8013 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8015 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]);
8016 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8017 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]);
8018 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8019 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]);
8022 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8023 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]);
8024 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8026 // if this is opaque use alpha blend which will darken the earlier
8029 // if this is an alpha blended material, all the earlier passes
8030 // were darkened by fog already, so we only need to add the fog
8031 // color ontop through the fog mask texture
8033 // if this is an additive blended material, all the earlier passes
8034 // were darkened by fog already, and we should not add fog color
8035 // (because the background was not darkened, there is no fog color
8036 // that was lost behind it).
8037 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]);
8041 return t->currentframe;
8044 rsurfacestate_t rsurface;
8046 void RSurf_ActiveWorldEntity(void)
8048 dp_model_t *model = r_refdef.scene.worldmodel;
8049 //if (rsurface.entity == r_refdef.scene.worldentity)
8051 rsurface.entity = r_refdef.scene.worldentity;
8052 rsurface.skeleton = NULL;
8053 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8054 rsurface.ent_skinnum = 0;
8055 rsurface.ent_qwskin = -1;
8056 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8057 rsurface.shadertime = r_refdef.scene.time;
8058 rsurface.matrix = identitymatrix;
8059 rsurface.inversematrix = identitymatrix;
8060 rsurface.matrixscale = 1;
8061 rsurface.inversematrixscale = 1;
8062 R_EntityMatrix(&identitymatrix);
8063 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8064 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8065 rsurface.fograngerecip = r_refdef.fograngerecip;
8066 rsurface.fogheightfade = r_refdef.fogheightfade;
8067 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8068 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8069 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8070 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8071 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8072 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8073 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8074 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8075 rsurface.colormod[3] = 1;
8076 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);
8077 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8078 rsurface.frameblend[0].lerp = 1;
8079 rsurface.ent_alttextures = false;
8080 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8081 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8082 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8083 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8084 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8085 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8086 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8087 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8088 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8089 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8090 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8091 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8092 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8093 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8094 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8095 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8096 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8097 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8098 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8099 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8100 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8101 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8102 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8103 rsurface.modelelement3i = model->surfmesh.data_element3i;
8104 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8105 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8106 rsurface.modelelement3s = model->surfmesh.data_element3s;
8107 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8108 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8109 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8110 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8111 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8112 rsurface.modelsurfaces = model->data_surfaces;
8113 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8114 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8115 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8116 rsurface.modelgeneratedvertex = false;
8117 rsurface.batchgeneratedvertex = false;
8118 rsurface.batchfirstvertex = 0;
8119 rsurface.batchnumvertices = 0;
8120 rsurface.batchfirsttriangle = 0;
8121 rsurface.batchnumtriangles = 0;
8122 rsurface.batchvertex3f = NULL;
8123 rsurface.batchvertex3f_vertexbuffer = NULL;
8124 rsurface.batchvertex3f_bufferoffset = 0;
8125 rsurface.batchsvector3f = NULL;
8126 rsurface.batchsvector3f_vertexbuffer = NULL;
8127 rsurface.batchsvector3f_bufferoffset = 0;
8128 rsurface.batchtvector3f = NULL;
8129 rsurface.batchtvector3f_vertexbuffer = NULL;
8130 rsurface.batchtvector3f_bufferoffset = 0;
8131 rsurface.batchnormal3f = NULL;
8132 rsurface.batchnormal3f_vertexbuffer = NULL;
8133 rsurface.batchnormal3f_bufferoffset = 0;
8134 rsurface.batchlightmapcolor4f = NULL;
8135 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8136 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8137 rsurface.batchtexcoordtexture2f = NULL;
8138 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8139 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8140 rsurface.batchtexcoordlightmap2f = NULL;
8141 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8142 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8143 rsurface.batchvertexmesh = NULL;
8144 rsurface.batchvertexmeshbuffer = NULL;
8145 rsurface.batchvertex3fbuffer = NULL;
8146 rsurface.batchelement3i = NULL;
8147 rsurface.batchelement3i_indexbuffer = NULL;
8148 rsurface.batchelement3i_bufferoffset = 0;
8149 rsurface.batchelement3s = NULL;
8150 rsurface.batchelement3s_indexbuffer = NULL;
8151 rsurface.batchelement3s_bufferoffset = 0;
8152 rsurface.passcolor4f = NULL;
8153 rsurface.passcolor4f_vertexbuffer = NULL;
8154 rsurface.passcolor4f_bufferoffset = 0;
8157 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8159 dp_model_t *model = ent->model;
8160 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8162 rsurface.entity = (entity_render_t *)ent;
8163 rsurface.skeleton = ent->skeleton;
8164 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8165 rsurface.ent_skinnum = ent->skinnum;
8166 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;
8167 rsurface.ent_flags = ent->flags;
8168 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8169 rsurface.matrix = ent->matrix;
8170 rsurface.inversematrix = ent->inversematrix;
8171 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8172 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8173 R_EntityMatrix(&rsurface.matrix);
8174 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8175 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8176 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8177 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8178 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8179 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8180 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8181 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8182 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8183 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8184 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8185 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8186 rsurface.colormod[3] = ent->alpha;
8187 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8188 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8189 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8190 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8191 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8192 if (ent->model->brush.submodel && !prepass)
8194 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8195 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8197 if (model->surfmesh.isanimated && model->AnimateVertices)
8199 if (ent->animcache_vertex3f)
8201 rsurface.modelvertex3f = ent->animcache_vertex3f;
8202 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8203 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8204 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8205 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8206 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8207 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8209 else if (wanttangents)
8211 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8212 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8213 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8214 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8215 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8216 rsurface.modelvertexmesh = NULL;
8217 rsurface.modelvertexmeshbuffer = NULL;
8218 rsurface.modelvertex3fbuffer = NULL;
8220 else if (wantnormals)
8222 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8223 rsurface.modelsvector3f = NULL;
8224 rsurface.modeltvector3f = NULL;
8225 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8226 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8227 rsurface.modelvertexmesh = NULL;
8228 rsurface.modelvertexmeshbuffer = NULL;
8229 rsurface.modelvertex3fbuffer = NULL;
8233 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8234 rsurface.modelsvector3f = NULL;
8235 rsurface.modeltvector3f = NULL;
8236 rsurface.modelnormal3f = NULL;
8237 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8238 rsurface.modelvertexmesh = NULL;
8239 rsurface.modelvertexmeshbuffer = NULL;
8240 rsurface.modelvertex3fbuffer = NULL;
8242 rsurface.modelvertex3f_vertexbuffer = 0;
8243 rsurface.modelvertex3f_bufferoffset = 0;
8244 rsurface.modelsvector3f_vertexbuffer = 0;
8245 rsurface.modelsvector3f_bufferoffset = 0;
8246 rsurface.modeltvector3f_vertexbuffer = 0;
8247 rsurface.modeltvector3f_bufferoffset = 0;
8248 rsurface.modelnormal3f_vertexbuffer = 0;
8249 rsurface.modelnormal3f_bufferoffset = 0;
8250 rsurface.modelgeneratedvertex = true;
8254 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8255 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8256 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8257 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8258 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8259 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8260 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8261 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8262 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8263 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8264 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8265 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8266 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8267 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8268 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8269 rsurface.modelgeneratedvertex = false;
8271 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8272 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8273 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8274 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8275 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8276 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8277 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8278 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8279 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8280 rsurface.modelelement3i = model->surfmesh.data_element3i;
8281 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8282 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8283 rsurface.modelelement3s = model->surfmesh.data_element3s;
8284 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8285 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8286 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8287 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8288 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8289 rsurface.modelsurfaces = model->data_surfaces;
8290 rsurface.batchgeneratedvertex = false;
8291 rsurface.batchfirstvertex = 0;
8292 rsurface.batchnumvertices = 0;
8293 rsurface.batchfirsttriangle = 0;
8294 rsurface.batchnumtriangles = 0;
8295 rsurface.batchvertex3f = NULL;
8296 rsurface.batchvertex3f_vertexbuffer = NULL;
8297 rsurface.batchvertex3f_bufferoffset = 0;
8298 rsurface.batchsvector3f = NULL;
8299 rsurface.batchsvector3f_vertexbuffer = NULL;
8300 rsurface.batchsvector3f_bufferoffset = 0;
8301 rsurface.batchtvector3f = NULL;
8302 rsurface.batchtvector3f_vertexbuffer = NULL;
8303 rsurface.batchtvector3f_bufferoffset = 0;
8304 rsurface.batchnormal3f = NULL;
8305 rsurface.batchnormal3f_vertexbuffer = NULL;
8306 rsurface.batchnormal3f_bufferoffset = 0;
8307 rsurface.batchlightmapcolor4f = NULL;
8308 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8309 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8310 rsurface.batchtexcoordtexture2f = NULL;
8311 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8312 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8313 rsurface.batchtexcoordlightmap2f = NULL;
8314 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8315 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8316 rsurface.batchvertexmesh = NULL;
8317 rsurface.batchvertexmeshbuffer = NULL;
8318 rsurface.batchvertex3fbuffer = NULL;
8319 rsurface.batchelement3i = NULL;
8320 rsurface.batchelement3i_indexbuffer = NULL;
8321 rsurface.batchelement3i_bufferoffset = 0;
8322 rsurface.batchelement3s = NULL;
8323 rsurface.batchelement3s_indexbuffer = NULL;
8324 rsurface.batchelement3s_bufferoffset = 0;
8325 rsurface.passcolor4f = NULL;
8326 rsurface.passcolor4f_vertexbuffer = NULL;
8327 rsurface.passcolor4f_bufferoffset = 0;
8330 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)
8332 rsurface.entity = r_refdef.scene.worldentity;
8333 rsurface.skeleton = NULL;
8334 rsurface.ent_skinnum = 0;
8335 rsurface.ent_qwskin = -1;
8336 rsurface.ent_flags = entflags;
8337 rsurface.shadertime = r_refdef.scene.time - shadertime;
8338 rsurface.modelnumvertices = numvertices;
8339 rsurface.modelnumtriangles = numtriangles;
8340 rsurface.matrix = *matrix;
8341 rsurface.inversematrix = *inversematrix;
8342 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8343 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8344 R_EntityMatrix(&rsurface.matrix);
8345 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8346 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8347 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8348 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8349 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8350 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8351 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8352 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8353 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8354 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8355 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8356 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8357 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);
8358 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8359 rsurface.frameblend[0].lerp = 1;
8360 rsurface.ent_alttextures = false;
8361 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8362 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8365 rsurface.modelvertex3f = (float *)vertex3f;
8366 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8367 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8368 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8370 else if (wantnormals)
8372 rsurface.modelvertex3f = (float *)vertex3f;
8373 rsurface.modelsvector3f = NULL;
8374 rsurface.modeltvector3f = NULL;
8375 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8379 rsurface.modelvertex3f = (float *)vertex3f;
8380 rsurface.modelsvector3f = NULL;
8381 rsurface.modeltvector3f = NULL;
8382 rsurface.modelnormal3f = NULL;
8384 rsurface.modelvertexmesh = NULL;
8385 rsurface.modelvertexmeshbuffer = NULL;
8386 rsurface.modelvertex3fbuffer = NULL;
8387 rsurface.modelvertex3f_vertexbuffer = 0;
8388 rsurface.modelvertex3f_bufferoffset = 0;
8389 rsurface.modelsvector3f_vertexbuffer = 0;
8390 rsurface.modelsvector3f_bufferoffset = 0;
8391 rsurface.modeltvector3f_vertexbuffer = 0;
8392 rsurface.modeltvector3f_bufferoffset = 0;
8393 rsurface.modelnormal3f_vertexbuffer = 0;
8394 rsurface.modelnormal3f_bufferoffset = 0;
8395 rsurface.modelgeneratedvertex = true;
8396 rsurface.modellightmapcolor4f = (float *)color4f;
8397 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8398 rsurface.modellightmapcolor4f_bufferoffset = 0;
8399 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8400 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8401 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8402 rsurface.modeltexcoordlightmap2f = NULL;
8403 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8404 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8405 rsurface.modelelement3i = (int *)element3i;
8406 rsurface.modelelement3i_indexbuffer = NULL;
8407 rsurface.modelelement3i_bufferoffset = 0;
8408 rsurface.modelelement3s = (unsigned short *)element3s;
8409 rsurface.modelelement3s_indexbuffer = NULL;
8410 rsurface.modelelement3s_bufferoffset = 0;
8411 rsurface.modellightmapoffsets = NULL;
8412 rsurface.modelsurfaces = NULL;
8413 rsurface.batchgeneratedvertex = false;
8414 rsurface.batchfirstvertex = 0;
8415 rsurface.batchnumvertices = 0;
8416 rsurface.batchfirsttriangle = 0;
8417 rsurface.batchnumtriangles = 0;
8418 rsurface.batchvertex3f = NULL;
8419 rsurface.batchvertex3f_vertexbuffer = NULL;
8420 rsurface.batchvertex3f_bufferoffset = 0;
8421 rsurface.batchsvector3f = NULL;
8422 rsurface.batchsvector3f_vertexbuffer = NULL;
8423 rsurface.batchsvector3f_bufferoffset = 0;
8424 rsurface.batchtvector3f = NULL;
8425 rsurface.batchtvector3f_vertexbuffer = NULL;
8426 rsurface.batchtvector3f_bufferoffset = 0;
8427 rsurface.batchnormal3f = NULL;
8428 rsurface.batchnormal3f_vertexbuffer = NULL;
8429 rsurface.batchnormal3f_bufferoffset = 0;
8430 rsurface.batchlightmapcolor4f = NULL;
8431 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8432 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8433 rsurface.batchtexcoordtexture2f = NULL;
8434 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8435 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8436 rsurface.batchtexcoordlightmap2f = NULL;
8437 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8438 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8439 rsurface.batchvertexmesh = NULL;
8440 rsurface.batchvertexmeshbuffer = NULL;
8441 rsurface.batchvertex3fbuffer = NULL;
8442 rsurface.batchelement3i = NULL;
8443 rsurface.batchelement3i_indexbuffer = NULL;
8444 rsurface.batchelement3i_bufferoffset = 0;
8445 rsurface.batchelement3s = NULL;
8446 rsurface.batchelement3s_indexbuffer = NULL;
8447 rsurface.batchelement3s_bufferoffset = 0;
8448 rsurface.passcolor4f = NULL;
8449 rsurface.passcolor4f_vertexbuffer = NULL;
8450 rsurface.passcolor4f_bufferoffset = 0;
8452 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8454 if ((wantnormals || wanttangents) && !normal3f)
8456 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8457 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8459 if (wanttangents && !svector3f)
8461 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8462 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8463 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8468 float RSurf_FogPoint(const float *v)
8470 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8471 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8472 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8473 float FogHeightFade = r_refdef.fogheightfade;
8475 unsigned int fogmasktableindex;
8476 if (r_refdef.fogplaneviewabove)
8477 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8479 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8480 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8481 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8484 float RSurf_FogVertex(const float *v)
8486 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8487 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8488 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8489 float FogHeightFade = rsurface.fogheightfade;
8491 unsigned int fogmasktableindex;
8492 if (r_refdef.fogplaneviewabove)
8493 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8495 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8496 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8497 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8500 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8503 for (i = 0;i < numelements;i++)
8504 outelement3i[i] = inelement3i[i] + adjust;
8507 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8508 extern cvar_t gl_vbo;
8509 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8517 int surfacefirsttriangle;
8518 int surfacenumtriangles;
8519 int surfacefirstvertex;
8520 int surfaceendvertex;
8521 int surfacenumvertices;
8522 int batchnumvertices;
8523 int batchnumtriangles;
8527 qboolean dynamicvertex;
8531 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8533 q3shaderinfo_deform_t *deform;
8534 const msurface_t *surface, *firstsurface;
8535 r_vertexmesh_t *vertexmesh;
8536 if (!texturenumsurfaces)
8538 // find vertex range of this surface batch
8540 firstsurface = texturesurfacelist[0];
8541 firsttriangle = firstsurface->num_firsttriangle;
8542 batchnumvertices = 0;
8543 batchnumtriangles = 0;
8544 firstvertex = endvertex = firstsurface->num_firstvertex;
8545 for (i = 0;i < texturenumsurfaces;i++)
8547 surface = texturesurfacelist[i];
8548 if (surface != firstsurface + i)
8550 surfacefirstvertex = surface->num_firstvertex;
8551 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8552 surfacenumvertices = surface->num_vertices;
8553 surfacenumtriangles = surface->num_triangles;
8554 if (firstvertex > surfacefirstvertex)
8555 firstvertex = surfacefirstvertex;
8556 if (endvertex < surfaceendvertex)
8557 endvertex = surfaceendvertex;
8558 batchnumvertices += surfacenumvertices;
8559 batchnumtriangles += surfacenumtriangles;
8562 // we now know the vertex range used, and if there are any gaps in it
8563 rsurface.batchfirstvertex = firstvertex;
8564 rsurface.batchnumvertices = endvertex - firstvertex;
8565 rsurface.batchfirsttriangle = firsttriangle;
8566 rsurface.batchnumtriangles = batchnumtriangles;
8568 // this variable holds flags for which properties have been updated that
8569 // may require regenerating vertexmesh array...
8572 // check if any dynamic vertex processing must occur
8573 dynamicvertex = false;
8575 // if there is a chance of animated vertex colors, it's a dynamic batch
8576 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8578 dynamicvertex = true;
8579 batchneed |= BATCHNEED_NOGAPS;
8580 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8583 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8585 switch (deform->deform)
8588 case Q3DEFORM_PROJECTIONSHADOW:
8589 case Q3DEFORM_TEXT0:
8590 case Q3DEFORM_TEXT1:
8591 case Q3DEFORM_TEXT2:
8592 case Q3DEFORM_TEXT3:
8593 case Q3DEFORM_TEXT4:
8594 case Q3DEFORM_TEXT5:
8595 case Q3DEFORM_TEXT6:
8596 case Q3DEFORM_TEXT7:
8599 case Q3DEFORM_AUTOSPRITE:
8600 dynamicvertex = true;
8601 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8602 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8604 case Q3DEFORM_AUTOSPRITE2:
8605 dynamicvertex = true;
8606 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8607 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8609 case Q3DEFORM_NORMAL:
8610 dynamicvertex = true;
8611 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8612 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8615 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8616 break; // if wavefunc is a nop, ignore this transform
8617 dynamicvertex = true;
8618 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8619 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8621 case Q3DEFORM_BULGE:
8622 dynamicvertex = true;
8623 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8624 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8627 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8628 break; // if wavefunc is a nop, ignore this transform
8629 dynamicvertex = true;
8630 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8631 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8635 switch(rsurface.texture->tcgen.tcgen)
8638 case Q3TCGEN_TEXTURE:
8640 case Q3TCGEN_LIGHTMAP:
8641 dynamicvertex = true;
8642 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8643 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8645 case Q3TCGEN_VECTOR:
8646 dynamicvertex = true;
8647 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8648 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8650 case Q3TCGEN_ENVIRONMENT:
8651 dynamicvertex = true;
8652 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8653 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8656 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8658 dynamicvertex = true;
8659 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8660 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8663 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8665 dynamicvertex = true;
8666 batchneed |= BATCHNEED_NOGAPS;
8667 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8670 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8672 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8673 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8674 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8675 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8676 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8677 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8678 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8681 // when the model data has no vertex buffer (dynamic mesh), we need to
8683 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8684 batchneed |= BATCHNEED_NOGAPS;
8686 // if needsupdate, we have to do a dynamic vertex batch for sure
8687 if (needsupdate & batchneed)
8688 dynamicvertex = true;
8690 // see if we need to build vertexmesh from arrays
8691 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8692 dynamicvertex = true;
8694 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8695 // also some drivers strongly dislike firstvertex
8696 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8697 dynamicvertex = true;
8699 rsurface.batchvertex3f = rsurface.modelvertex3f;
8700 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8701 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8702 rsurface.batchsvector3f = rsurface.modelsvector3f;
8703 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8704 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8705 rsurface.batchtvector3f = rsurface.modeltvector3f;
8706 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8707 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8708 rsurface.batchnormal3f = rsurface.modelnormal3f;
8709 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8710 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8711 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8712 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8713 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8714 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8715 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8716 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8717 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8718 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8719 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8720 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8721 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8722 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8723 rsurface.batchelement3i = rsurface.modelelement3i;
8724 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8725 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8726 rsurface.batchelement3s = rsurface.modelelement3s;
8727 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8728 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8730 // if any dynamic vertex processing has to occur in software, we copy the
8731 // entire surface list together before processing to rebase the vertices
8732 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8734 // if any gaps exist and we do not have a static vertex buffer, we have to
8735 // copy the surface list together to avoid wasting upload bandwidth on the
8736 // vertices in the gaps.
8738 // if gaps exist and we have a static vertex buffer, we still have to
8739 // combine the index buffer ranges into one dynamic index buffer.
8741 // in all cases we end up with data that can be drawn in one call.
8745 // static vertex data, just set pointers...
8746 rsurface.batchgeneratedvertex = false;
8747 // if there are gaps, we want to build a combined index buffer,
8748 // otherwise use the original static buffer with an appropriate offset
8751 // build a new triangle elements array for this batch
8752 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8753 rsurface.batchfirsttriangle = 0;
8755 for (i = 0;i < texturenumsurfaces;i++)
8757 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8758 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8759 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8760 numtriangles += surfacenumtriangles;
8762 rsurface.batchelement3i_indexbuffer = NULL;
8763 rsurface.batchelement3i_bufferoffset = 0;
8764 rsurface.batchelement3s = NULL;
8765 rsurface.batchelement3s_indexbuffer = NULL;
8766 rsurface.batchelement3s_bufferoffset = 0;
8767 if (endvertex <= 65536)
8769 // make a 16bit (unsigned short) index array if possible
8770 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8771 for (i = 0;i < numtriangles*3;i++)
8772 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8778 // something needs software processing, do it for real...
8779 // we only directly handle separate array data in this case and then
8780 // generate interleaved data if needed...
8781 rsurface.batchgeneratedvertex = true;
8783 // now copy the vertex data into a combined array and make an index array
8784 // (this is what Quake3 does all the time)
8785 //if (gaps || rsurface.batchfirstvertex)
8787 rsurface.batchvertex3fbuffer = NULL;
8788 rsurface.batchvertexmesh = NULL;
8789 rsurface.batchvertexmeshbuffer = NULL;
8790 rsurface.batchvertex3f = NULL;
8791 rsurface.batchvertex3f_vertexbuffer = NULL;
8792 rsurface.batchvertex3f_bufferoffset = 0;
8793 rsurface.batchsvector3f = NULL;
8794 rsurface.batchsvector3f_vertexbuffer = NULL;
8795 rsurface.batchsvector3f_bufferoffset = 0;
8796 rsurface.batchtvector3f = NULL;
8797 rsurface.batchtvector3f_vertexbuffer = NULL;
8798 rsurface.batchtvector3f_bufferoffset = 0;
8799 rsurface.batchnormal3f = NULL;
8800 rsurface.batchnormal3f_vertexbuffer = NULL;
8801 rsurface.batchnormal3f_bufferoffset = 0;
8802 rsurface.batchlightmapcolor4f = NULL;
8803 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8804 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8805 rsurface.batchtexcoordtexture2f = NULL;
8806 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8807 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8808 rsurface.batchtexcoordlightmap2f = NULL;
8809 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8810 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8811 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8812 rsurface.batchelement3i_indexbuffer = NULL;
8813 rsurface.batchelement3i_bufferoffset = 0;
8814 rsurface.batchelement3s = NULL;
8815 rsurface.batchelement3s_indexbuffer = NULL;
8816 rsurface.batchelement3s_bufferoffset = 0;
8817 // we'll only be setting up certain arrays as needed
8818 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8819 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8820 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8821 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8822 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8823 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8824 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8826 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8827 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8829 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8830 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8831 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8832 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8833 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8834 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8837 for (i = 0;i < texturenumsurfaces;i++)
8839 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8840 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8841 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8842 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8843 // copy only the data requested
8844 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8845 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8846 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8848 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8850 if (rsurface.batchvertex3f)
8851 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8853 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8855 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8857 if (rsurface.modelnormal3f)
8858 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8860 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8862 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8864 if (rsurface.modelsvector3f)
8866 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8867 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8871 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8872 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8875 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8877 if (rsurface.modellightmapcolor4f)
8878 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8880 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8882 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8884 if (rsurface.modeltexcoordtexture2f)
8885 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8887 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8889 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8891 if (rsurface.modeltexcoordlightmap2f)
8892 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8894 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8897 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8898 numvertices += surfacenumvertices;
8899 numtriangles += surfacenumtriangles;
8902 // generate a 16bit index array as well if possible
8903 // (in general, dynamic batches fit)
8904 if (numvertices <= 65536)
8906 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8907 for (i = 0;i < numtriangles*3;i++)
8908 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8911 // since we've copied everything, the batch now starts at 0
8912 rsurface.batchfirstvertex = 0;
8913 rsurface.batchnumvertices = batchnumvertices;
8914 rsurface.batchfirsttriangle = 0;
8915 rsurface.batchnumtriangles = batchnumtriangles;
8918 // q1bsp surfaces rendered in vertex color mode have to have colors
8919 // calculated based on lightstyles
8920 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8922 // generate color arrays for the surfaces in this list
8927 const unsigned char *lm;
8928 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8929 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8930 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8932 for (i = 0;i < texturenumsurfaces;i++)
8934 surface = texturesurfacelist[i];
8935 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8936 surfacenumvertices = surface->num_vertices;
8937 if (surface->lightmapinfo->samples)
8939 for (j = 0;j < surfacenumvertices;j++)
8941 lm = surface->lightmapinfo->samples + offsets[j];
8942 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8943 VectorScale(lm, scale, c);
8944 if (surface->lightmapinfo->styles[1] != 255)
8946 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8948 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8949 VectorMA(c, scale, lm, c);
8950 if (surface->lightmapinfo->styles[2] != 255)
8953 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8954 VectorMA(c, scale, lm, c);
8955 if (surface->lightmapinfo->styles[3] != 255)
8958 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8959 VectorMA(c, scale, lm, c);
8966 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);
8972 for (j = 0;j < surfacenumvertices;j++)
8974 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8981 // if vertices are deformed (sprite flares and things in maps, possibly
8982 // water waves, bulges and other deformations), modify the copied vertices
8984 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8986 switch (deform->deform)
8989 case Q3DEFORM_PROJECTIONSHADOW:
8990 case Q3DEFORM_TEXT0:
8991 case Q3DEFORM_TEXT1:
8992 case Q3DEFORM_TEXT2:
8993 case Q3DEFORM_TEXT3:
8994 case Q3DEFORM_TEXT4:
8995 case Q3DEFORM_TEXT5:
8996 case Q3DEFORM_TEXT6:
8997 case Q3DEFORM_TEXT7:
9000 case Q3DEFORM_AUTOSPRITE:
9001 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9002 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9003 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9004 VectorNormalize(newforward);
9005 VectorNormalize(newright);
9006 VectorNormalize(newup);
9007 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9008 // rsurface.batchvertex3f_vertexbuffer = NULL;
9009 // rsurface.batchvertex3f_bufferoffset = 0;
9010 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9011 // rsurface.batchsvector3f_vertexbuffer = NULL;
9012 // rsurface.batchsvector3f_bufferoffset = 0;
9013 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9014 // rsurface.batchtvector3f_vertexbuffer = NULL;
9015 // rsurface.batchtvector3f_bufferoffset = 0;
9016 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9017 // rsurface.batchnormal3f_vertexbuffer = NULL;
9018 // rsurface.batchnormal3f_bufferoffset = 0;
9019 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9020 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9021 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9022 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9023 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);
9024 // a single autosprite surface can contain multiple sprites...
9025 for (j = 0;j < batchnumvertices - 3;j += 4)
9027 VectorClear(center);
9028 for (i = 0;i < 4;i++)
9029 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9030 VectorScale(center, 0.25f, center);
9031 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9032 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9033 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9034 for (i = 0;i < 4;i++)
9036 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9037 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9040 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9041 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9042 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);
9044 case Q3DEFORM_AUTOSPRITE2:
9045 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9046 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9047 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9048 VectorNormalize(newforward);
9049 VectorNormalize(newright);
9050 VectorNormalize(newup);
9051 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9052 // rsurface.batchvertex3f_vertexbuffer = NULL;
9053 // rsurface.batchvertex3f_bufferoffset = 0;
9055 const float *v1, *v2;
9065 memset(shortest, 0, sizeof(shortest));
9066 // a single autosprite surface can contain multiple sprites...
9067 for (j = 0;j < batchnumvertices - 3;j += 4)
9069 VectorClear(center);
9070 for (i = 0;i < 4;i++)
9071 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9072 VectorScale(center, 0.25f, center);
9073 // find the two shortest edges, then use them to define the
9074 // axis vectors for rotating around the central axis
9075 for (i = 0;i < 6;i++)
9077 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9078 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9079 l = VectorDistance2(v1, v2);
9080 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9082 l += (1.0f / 1024.0f);
9083 if (shortest[0].length2 > l || i == 0)
9085 shortest[1] = shortest[0];
9086 shortest[0].length2 = l;
9087 shortest[0].v1 = v1;
9088 shortest[0].v2 = v2;
9090 else if (shortest[1].length2 > l || i == 1)
9092 shortest[1].length2 = l;
9093 shortest[1].v1 = v1;
9094 shortest[1].v2 = v2;
9097 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9098 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9099 // this calculates the right vector from the shortest edge
9100 // and the up vector from the edge midpoints
9101 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9102 VectorNormalize(right);
9103 VectorSubtract(end, start, up);
9104 VectorNormalize(up);
9105 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9106 VectorSubtract(rsurface.localvieworigin, center, forward);
9107 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9108 VectorNegate(forward, forward);
9109 VectorReflect(forward, 0, up, forward);
9110 VectorNormalize(forward);
9111 CrossProduct(up, forward, newright);
9112 VectorNormalize(newright);
9113 // rotate the quad around the up axis vector, this is made
9114 // especially easy by the fact we know the quad is flat,
9115 // so we only have to subtract the center position and
9116 // measure distance along the right vector, and then
9117 // multiply that by the newright vector and add back the
9119 // we also need to subtract the old position to undo the
9120 // displacement from the center, which we do with a
9121 // DotProduct, the subtraction/addition of center is also
9122 // optimized into DotProducts here
9123 l = DotProduct(right, center);
9124 for (i = 0;i < 4;i++)
9126 v1 = rsurface.batchvertex3f + 3*(j+i);
9127 f = DotProduct(right, v1) - l;
9128 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9132 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9134 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9135 // rsurface.batchnormal3f_vertexbuffer = NULL;
9136 // rsurface.batchnormal3f_bufferoffset = 0;
9137 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9139 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9141 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9142 // rsurface.batchsvector3f_vertexbuffer = NULL;
9143 // rsurface.batchsvector3f_bufferoffset = 0;
9144 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9145 // rsurface.batchtvector3f_vertexbuffer = NULL;
9146 // rsurface.batchtvector3f_bufferoffset = 0;
9147 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);
9150 case Q3DEFORM_NORMAL:
9151 // deform the normals to make reflections wavey
9152 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9153 rsurface.batchnormal3f_vertexbuffer = NULL;
9154 rsurface.batchnormal3f_bufferoffset = 0;
9155 for (j = 0;j < batchnumvertices;j++)
9158 float *normal = rsurface.batchnormal3f + 3*j;
9159 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9160 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9161 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9162 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9163 VectorNormalize(normal);
9165 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9167 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9168 // rsurface.batchsvector3f_vertexbuffer = NULL;
9169 // rsurface.batchsvector3f_bufferoffset = 0;
9170 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9171 // rsurface.batchtvector3f_vertexbuffer = NULL;
9172 // rsurface.batchtvector3f_bufferoffset = 0;
9173 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);
9177 // deform vertex array to make wavey water and flags and such
9178 waveparms[0] = deform->waveparms[0];
9179 waveparms[1] = deform->waveparms[1];
9180 waveparms[2] = deform->waveparms[2];
9181 waveparms[3] = deform->waveparms[3];
9182 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9183 break; // if wavefunc is a nop, don't make a dynamic vertex array
9184 // this is how a divisor of vertex influence on deformation
9185 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9186 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9187 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9188 // rsurface.batchvertex3f_vertexbuffer = NULL;
9189 // rsurface.batchvertex3f_bufferoffset = 0;
9190 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9191 // rsurface.batchnormal3f_vertexbuffer = NULL;
9192 // rsurface.batchnormal3f_bufferoffset = 0;
9193 for (j = 0;j < batchnumvertices;j++)
9195 // if the wavefunc depends on time, evaluate it per-vertex
9198 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9199 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9201 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9203 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9204 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9205 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9207 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9208 // rsurface.batchsvector3f_vertexbuffer = NULL;
9209 // rsurface.batchsvector3f_bufferoffset = 0;
9210 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9211 // rsurface.batchtvector3f_vertexbuffer = NULL;
9212 // rsurface.batchtvector3f_bufferoffset = 0;
9213 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);
9216 case Q3DEFORM_BULGE:
9217 // deform vertex array to make the surface have moving bulges
9218 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9219 // rsurface.batchvertex3f_vertexbuffer = NULL;
9220 // rsurface.batchvertex3f_bufferoffset = 0;
9221 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9222 // rsurface.batchnormal3f_vertexbuffer = NULL;
9223 // rsurface.batchnormal3f_bufferoffset = 0;
9224 for (j = 0;j < batchnumvertices;j++)
9226 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9227 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9229 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9230 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9231 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9233 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9234 // rsurface.batchsvector3f_vertexbuffer = NULL;
9235 // rsurface.batchsvector3f_bufferoffset = 0;
9236 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9237 // rsurface.batchtvector3f_vertexbuffer = NULL;
9238 // rsurface.batchtvector3f_bufferoffset = 0;
9239 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);
9243 // deform vertex array
9244 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9245 break; // if wavefunc is a nop, don't make a dynamic vertex array
9246 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9247 VectorScale(deform->parms, scale, waveparms);
9248 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9249 // rsurface.batchvertex3f_vertexbuffer = NULL;
9250 // rsurface.batchvertex3f_bufferoffset = 0;
9251 for (j = 0;j < batchnumvertices;j++)
9252 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9257 // generate texcoords based on the chosen texcoord source
9258 switch(rsurface.texture->tcgen.tcgen)
9261 case Q3TCGEN_TEXTURE:
9263 case Q3TCGEN_LIGHTMAP:
9264 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9265 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9266 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9267 if (rsurface.batchtexcoordlightmap2f)
9268 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9270 case Q3TCGEN_VECTOR:
9271 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9272 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9273 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9274 for (j = 0;j < batchnumvertices;j++)
9276 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9277 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9280 case Q3TCGEN_ENVIRONMENT:
9281 // make environment reflections using a spheremap
9282 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9283 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9284 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9285 for (j = 0;j < batchnumvertices;j++)
9287 // identical to Q3A's method, but executed in worldspace so
9288 // carried models can be shiny too
9290 float viewer[3], d, reflected[3], worldreflected[3];
9292 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9293 // VectorNormalize(viewer);
9295 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9297 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9298 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9299 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9300 // note: this is proportinal to viewer, so we can normalize later
9302 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9303 VectorNormalize(worldreflected);
9305 // note: this sphere map only uses world x and z!
9306 // so positive and negative y will LOOK THE SAME.
9307 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9308 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9312 // the only tcmod that needs software vertex processing is turbulent, so
9313 // check for it here and apply the changes if needed
9314 // and we only support that as the first one
9315 // (handling a mixture of turbulent and other tcmods would be problematic
9316 // without punting it entirely to a software path)
9317 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9319 amplitude = rsurface.texture->tcmods[0].parms[1];
9320 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9321 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9322 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9323 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9324 for (j = 0;j < batchnumvertices;j++)
9326 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);
9327 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9331 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9333 // convert the modified arrays to vertex structs
9334 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9335 // rsurface.batchvertexmeshbuffer = NULL;
9336 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9337 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9338 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9339 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9340 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9341 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9342 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9344 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9346 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9347 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9350 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9351 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9352 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9353 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9354 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9355 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9356 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9357 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9358 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9362 void RSurf_DrawBatch(void)
9364 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9365 // through the pipeline, killing it earlier in the pipeline would have
9366 // per-surface overhead rather than per-batch overhead, so it's best to
9367 // reject it here, before it hits glDraw.
9368 if (rsurface.batchnumtriangles == 0)
9371 // batch debugging code
9372 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9378 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9379 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9382 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9384 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9386 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9387 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);
9394 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);
9397 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9399 // pick the closest matching water plane
9400 int planeindex, vertexindex, bestplaneindex = -1;
9404 r_waterstate_waterplane_t *p;
9405 qboolean prepared = false;
9407 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9409 if(p->camera_entity != rsurface.texture->camera_entity)
9414 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9416 if(rsurface.batchnumvertices == 0)
9419 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9421 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9422 d += fabs(PlaneDiff(vert, &p->plane));
9424 if (bestd > d || bestplaneindex < 0)
9427 bestplaneindex = planeindex;
9430 return bestplaneindex;
9431 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9432 // this situation though, as it might be better to render single larger
9433 // batches with useless stuff (backface culled for example) than to
9434 // render multiple smaller batches
9437 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9440 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9441 rsurface.passcolor4f_vertexbuffer = 0;
9442 rsurface.passcolor4f_bufferoffset = 0;
9443 for (i = 0;i < rsurface.batchnumvertices;i++)
9444 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9447 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9454 if (rsurface.passcolor4f)
9456 // generate color arrays
9457 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9458 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9459 rsurface.passcolor4f_vertexbuffer = 0;
9460 rsurface.passcolor4f_bufferoffset = 0;
9461 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)
9463 f = RSurf_FogVertex(v);
9472 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9473 rsurface.passcolor4f_vertexbuffer = 0;
9474 rsurface.passcolor4f_bufferoffset = 0;
9475 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9477 f = RSurf_FogVertex(v);
9486 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9493 if (!rsurface.passcolor4f)
9495 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9496 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9497 rsurface.passcolor4f_vertexbuffer = 0;
9498 rsurface.passcolor4f_bufferoffset = 0;
9499 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)
9501 f = RSurf_FogVertex(v);
9502 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9503 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9504 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9509 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9514 if (!rsurface.passcolor4f)
9516 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9517 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9518 rsurface.passcolor4f_vertexbuffer = 0;
9519 rsurface.passcolor4f_bufferoffset = 0;
9520 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9529 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9534 if (!rsurface.passcolor4f)
9536 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9537 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9538 rsurface.passcolor4f_vertexbuffer = 0;
9539 rsurface.passcolor4f_bufferoffset = 0;
9540 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9542 c2[0] = c[0] + r_refdef.scene.ambient;
9543 c2[1] = c[1] + r_refdef.scene.ambient;
9544 c2[2] = c[2] + r_refdef.scene.ambient;
9549 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9552 rsurface.passcolor4f = NULL;
9553 rsurface.passcolor4f_vertexbuffer = 0;
9554 rsurface.passcolor4f_bufferoffset = 0;
9555 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9556 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9557 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9558 GL_Color(r, g, b, a);
9559 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9563 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9565 // TODO: optimize applyfog && applycolor case
9566 // just apply fog if necessary, and tint the fog color array if necessary
9567 rsurface.passcolor4f = NULL;
9568 rsurface.passcolor4f_vertexbuffer = 0;
9569 rsurface.passcolor4f_bufferoffset = 0;
9570 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9571 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9572 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9573 GL_Color(r, g, b, a);
9577 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9580 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9581 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9582 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9583 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9584 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9585 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9586 GL_Color(r, g, b, a);
9590 static void RSurf_DrawBatch_GL11_ClampColor(void)
9595 if (!rsurface.passcolor4f)
9597 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9599 c2[0] = bound(0.0f, c1[0], 1.0f);
9600 c2[1] = bound(0.0f, c1[1], 1.0f);
9601 c2[2] = bound(0.0f, c1[2], 1.0f);
9602 c2[3] = bound(0.0f, c1[3], 1.0f);
9606 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9616 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9617 rsurface.passcolor4f_vertexbuffer = 0;
9618 rsurface.passcolor4f_bufferoffset = 0;
9619 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)
9621 f = -DotProduct(r_refdef.view.forward, n);
9623 f = f * 0.85 + 0.15; // work around so stuff won't get black
9624 f *= r_refdef.lightmapintensity;
9625 Vector4Set(c, f, f, f, 1);
9629 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9631 RSurf_DrawBatch_GL11_ApplyFakeLight();
9632 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9633 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9634 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9635 GL_Color(r, g, b, a);
9639 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9647 vec3_t ambientcolor;
9648 vec3_t diffusecolor;
9652 VectorCopy(rsurface.modellight_lightdir, lightdir);
9653 f = 0.5f * r_refdef.lightmapintensity;
9654 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9655 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9656 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9657 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9658 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9659 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9661 if (VectorLength2(diffusecolor) > 0)
9663 // q3-style directional shading
9664 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9665 rsurface.passcolor4f_vertexbuffer = 0;
9666 rsurface.passcolor4f_bufferoffset = 0;
9667 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)
9669 if ((f = DotProduct(n, lightdir)) > 0)
9670 VectorMA(ambientcolor, f, diffusecolor, c);
9672 VectorCopy(ambientcolor, c);
9679 *applycolor = false;
9683 *r = ambientcolor[0];
9684 *g = ambientcolor[1];
9685 *b = ambientcolor[2];
9686 rsurface.passcolor4f = NULL;
9687 rsurface.passcolor4f_vertexbuffer = 0;
9688 rsurface.passcolor4f_bufferoffset = 0;
9692 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9694 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9695 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9696 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9697 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9698 GL_Color(r, g, b, a);
9702 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9710 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9711 rsurface.passcolor4f_vertexbuffer = 0;
9712 rsurface.passcolor4f_bufferoffset = 0;
9714 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9716 f = 1 - RSurf_FogVertex(v);
9724 void RSurf_SetupDepthAndCulling(void)
9726 // submodels are biased to avoid z-fighting with world surfaces that they
9727 // may be exactly overlapping (avoids z-fighting artifacts on certain
9728 // doors and things in Quake maps)
9729 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9730 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9731 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9732 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9735 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9737 // transparent sky would be ridiculous
9738 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9740 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9741 skyrenderlater = true;
9742 RSurf_SetupDepthAndCulling();
9744 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9745 // skymasking on them, and Quake3 never did sky masking (unlike
9746 // software Quake and software Quake2), so disable the sky masking
9747 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9748 // and skymasking also looks very bad when noclipping outside the
9749 // level, so don't use it then either.
9750 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9752 R_Mesh_ResetTextureState();
9753 if (skyrendermasked)
9755 R_SetupShader_DepthOrShadow(false);
9756 // depth-only (masking)
9757 GL_ColorMask(0,0,0,0);
9758 // just to make sure that braindead drivers don't draw
9759 // anything despite that colormask...
9760 GL_BlendFunc(GL_ZERO, GL_ONE);
9761 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9762 if (rsurface.batchvertex3fbuffer)
9763 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9765 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9769 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9771 GL_BlendFunc(GL_ONE, GL_ZERO);
9772 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9773 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9774 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9777 if (skyrendermasked)
9778 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9780 R_Mesh_ResetTextureState();
9781 GL_Color(1, 1, 1, 1);
9784 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9785 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9786 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9788 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9792 // render screenspace normalmap to texture
9794 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9798 // bind lightmap texture
9800 // water/refraction/reflection/camera surfaces have to be handled specially
9801 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9803 int start, end, startplaneindex;
9804 for (start = 0;start < texturenumsurfaces;start = end)
9806 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9807 if(startplaneindex < 0)
9809 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9810 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9814 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9816 // now that we have a batch using the same planeindex, render it
9817 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9819 // render water or distortion background
9821 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);
9823 // blend surface on top
9824 GL_DepthMask(false);
9825 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9828 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9830 // render surface with reflection texture as input
9831 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9832 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);
9839 // render surface batch normally
9840 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9841 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);
9845 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9847 // OpenGL 1.3 path - anything not completely ancient
9848 qboolean applycolor;
9851 const texturelayer_t *layer;
9852 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);
9853 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9855 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9858 int layertexrgbscale;
9859 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9861 if (layerindex == 0)
9865 GL_AlphaTest(false);
9866 GL_DepthFunc(GL_EQUAL);
9869 GL_DepthMask(layer->depthmask && writedepth);
9870 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9871 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9873 layertexrgbscale = 4;
9874 VectorScale(layer->color, 0.25f, layercolor);
9876 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9878 layertexrgbscale = 2;
9879 VectorScale(layer->color, 0.5f, layercolor);
9883 layertexrgbscale = 1;
9884 VectorScale(layer->color, 1.0f, layercolor);
9886 layercolor[3] = layer->color[3];
9887 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9888 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9889 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9890 switch (layer->type)
9892 case TEXTURELAYERTYPE_LITTEXTURE:
9893 // single-pass lightmapped texture with 2x rgbscale
9894 R_Mesh_TexBind(0, r_texture_white);
9895 R_Mesh_TexMatrix(0, NULL);
9896 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9897 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9898 R_Mesh_TexBind(1, layer->texture);
9899 R_Mesh_TexMatrix(1, &layer->texmatrix);
9900 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9901 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9902 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9903 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9904 else if (FAKELIGHT_ENABLED)
9905 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9906 else if (rsurface.uselightmaptexture)
9907 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9909 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9911 case TEXTURELAYERTYPE_TEXTURE:
9912 // singletexture unlit texture with transparency support
9913 R_Mesh_TexBind(0, layer->texture);
9914 R_Mesh_TexMatrix(0, &layer->texmatrix);
9915 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9916 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9917 R_Mesh_TexBind(1, 0);
9918 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9919 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9921 case TEXTURELAYERTYPE_FOG:
9922 // singletexture fogging
9925 R_Mesh_TexBind(0, layer->texture);
9926 R_Mesh_TexMatrix(0, &layer->texmatrix);
9927 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9928 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9932 R_Mesh_TexBind(0, 0);
9933 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9935 R_Mesh_TexBind(1, 0);
9936 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9937 // generate a color array for the fog pass
9938 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9939 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9943 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9946 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9948 GL_DepthFunc(GL_LEQUAL);
9949 GL_AlphaTest(false);
9953 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9955 // OpenGL 1.1 - crusty old voodoo path
9958 const texturelayer_t *layer;
9959 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);
9960 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9962 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9964 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9966 if (layerindex == 0)
9970 GL_AlphaTest(false);
9971 GL_DepthFunc(GL_EQUAL);
9974 GL_DepthMask(layer->depthmask && writedepth);
9975 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9976 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9977 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9978 switch (layer->type)
9980 case TEXTURELAYERTYPE_LITTEXTURE:
9981 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9983 // two-pass lit texture with 2x rgbscale
9984 // first the lightmap pass
9985 R_Mesh_TexBind(0, r_texture_white);
9986 R_Mesh_TexMatrix(0, NULL);
9987 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9988 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9989 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9990 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9991 else if (FAKELIGHT_ENABLED)
9992 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9993 else if (rsurface.uselightmaptexture)
9994 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9996 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9997 // then apply the texture to it
9998 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9999 R_Mesh_TexBind(0, layer->texture);
10000 R_Mesh_TexMatrix(0, &layer->texmatrix);
10001 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10002 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10003 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);
10007 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10008 R_Mesh_TexBind(0, layer->texture);
10009 R_Mesh_TexMatrix(0, &layer->texmatrix);
10010 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10011 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10012 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10013 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);
10015 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);
10018 case TEXTURELAYERTYPE_TEXTURE:
10019 // singletexture unlit texture with transparency support
10020 R_Mesh_TexBind(0, layer->texture);
10021 R_Mesh_TexMatrix(0, &layer->texmatrix);
10022 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10023 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10024 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);
10026 case TEXTURELAYERTYPE_FOG:
10027 // singletexture fogging
10028 if (layer->texture)
10030 R_Mesh_TexBind(0, layer->texture);
10031 R_Mesh_TexMatrix(0, &layer->texmatrix);
10032 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10033 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10037 R_Mesh_TexBind(0, 0);
10038 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10040 // generate a color array for the fog pass
10041 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10042 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10046 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10049 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10051 GL_DepthFunc(GL_LEQUAL);
10052 GL_AlphaTest(false);
10056 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10060 r_vertexgeneric_t *batchvertex;
10063 // R_Mesh_ResetTextureState();
10064 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10066 if(rsurface.texture && rsurface.texture->currentskinframe)
10068 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10069 c[3] *= rsurface.texture->currentalpha;
10079 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10081 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10082 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10083 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10086 // brighten it up (as texture value 127 means "unlit")
10087 c[0] *= 2 * r_refdef.view.colorscale;
10088 c[1] *= 2 * r_refdef.view.colorscale;
10089 c[2] *= 2 * r_refdef.view.colorscale;
10091 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10092 c[3] *= r_wateralpha.value;
10094 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10096 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10097 GL_DepthMask(false);
10099 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10101 GL_BlendFunc(GL_ONE, GL_ONE);
10102 GL_DepthMask(false);
10104 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10106 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10107 GL_DepthMask(false);
10109 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10111 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10112 GL_DepthMask(false);
10116 GL_BlendFunc(GL_ONE, GL_ZERO);
10117 GL_DepthMask(writedepth);
10120 if (r_showsurfaces.integer == 3)
10122 rsurface.passcolor4f = NULL;
10124 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10126 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10128 rsurface.passcolor4f = NULL;
10129 rsurface.passcolor4f_vertexbuffer = 0;
10130 rsurface.passcolor4f_bufferoffset = 0;
10132 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10134 qboolean applycolor = true;
10137 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10139 r_refdef.lightmapintensity = 1;
10140 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10141 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10143 else if (FAKELIGHT_ENABLED)
10145 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10147 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10148 RSurf_DrawBatch_GL11_ApplyFakeLight();
10149 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10153 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10155 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10156 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10157 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10160 if(!rsurface.passcolor4f)
10161 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10163 RSurf_DrawBatch_GL11_ApplyAmbient();
10164 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10165 if(r_refdef.fogenabled)
10166 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10167 RSurf_DrawBatch_GL11_ClampColor();
10169 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10170 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10173 else if (!r_refdef.view.showdebug)
10175 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10176 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10177 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10179 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10180 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10182 R_Mesh_PrepareVertices_Generic_Unlock();
10185 else if (r_showsurfaces.integer == 4)
10187 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10188 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10189 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10191 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10192 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10193 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10195 R_Mesh_PrepareVertices_Generic_Unlock();
10198 else if (r_showsurfaces.integer == 2)
10201 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10202 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10203 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10205 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10206 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10207 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10208 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10209 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10210 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10211 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10213 R_Mesh_PrepareVertices_Generic_Unlock();
10214 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10218 int texturesurfaceindex;
10220 const msurface_t *surface;
10221 float surfacecolor4f[4];
10222 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10223 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10225 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10227 surface = texturesurfacelist[texturesurfaceindex];
10228 k = (int)(((size_t)surface) / sizeof(msurface_t));
10229 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10230 for (j = 0;j < surface->num_vertices;j++)
10232 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10233 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10237 R_Mesh_PrepareVertices_Generic_Unlock();
10242 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10245 RSurf_SetupDepthAndCulling();
10246 if (r_showsurfaces.integer)
10248 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10251 switch (vid.renderpath)
10253 case RENDERPATH_GL20:
10254 case RENDERPATH_D3D9:
10255 case RENDERPATH_D3D10:
10256 case RENDERPATH_D3D11:
10257 case RENDERPATH_SOFT:
10258 case RENDERPATH_GLES2:
10259 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10261 case RENDERPATH_GL13:
10262 case RENDERPATH_GLES1:
10263 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10265 case RENDERPATH_GL11:
10266 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10272 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10275 RSurf_SetupDepthAndCulling();
10276 if (r_showsurfaces.integer)
10278 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10281 switch (vid.renderpath)
10283 case RENDERPATH_GL20:
10284 case RENDERPATH_D3D9:
10285 case RENDERPATH_D3D10:
10286 case RENDERPATH_D3D11:
10287 case RENDERPATH_SOFT:
10288 case RENDERPATH_GLES2:
10289 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10291 case RENDERPATH_GL13:
10292 case RENDERPATH_GLES1:
10293 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10295 case RENDERPATH_GL11:
10296 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10302 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10305 int texturenumsurfaces, endsurface;
10306 texture_t *texture;
10307 const msurface_t *surface;
10308 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10310 // if the model is static it doesn't matter what value we give for
10311 // wantnormals and wanttangents, so this logic uses only rules applicable
10312 // to a model, knowing that they are meaningless otherwise
10313 if (ent == r_refdef.scene.worldentity)
10314 RSurf_ActiveWorldEntity();
10315 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10316 RSurf_ActiveModelEntity(ent, false, false, false);
10319 switch (vid.renderpath)
10321 case RENDERPATH_GL20:
10322 case RENDERPATH_D3D9:
10323 case RENDERPATH_D3D10:
10324 case RENDERPATH_D3D11:
10325 case RENDERPATH_SOFT:
10326 case RENDERPATH_GLES2:
10327 RSurf_ActiveModelEntity(ent, true, true, false);
10329 case RENDERPATH_GL11:
10330 case RENDERPATH_GL13:
10331 case RENDERPATH_GLES1:
10332 RSurf_ActiveModelEntity(ent, true, false, false);
10337 if (r_transparentdepthmasking.integer)
10339 qboolean setup = false;
10340 for (i = 0;i < numsurfaces;i = j)
10343 surface = rsurface.modelsurfaces + surfacelist[i];
10344 texture = surface->texture;
10345 rsurface.texture = R_GetCurrentTexture(texture);
10346 rsurface.lightmaptexture = NULL;
10347 rsurface.deluxemaptexture = NULL;
10348 rsurface.uselightmaptexture = false;
10349 // scan ahead until we find a different texture
10350 endsurface = min(i + 1024, numsurfaces);
10351 texturenumsurfaces = 0;
10352 texturesurfacelist[texturenumsurfaces++] = surface;
10353 for (;j < endsurface;j++)
10355 surface = rsurface.modelsurfaces + surfacelist[j];
10356 if (texture != surface->texture)
10358 texturesurfacelist[texturenumsurfaces++] = surface;
10360 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10362 // render the range of surfaces as depth
10366 GL_ColorMask(0,0,0,0);
10368 GL_DepthTest(true);
10369 GL_BlendFunc(GL_ONE, GL_ZERO);
10370 GL_DepthMask(true);
10371 // R_Mesh_ResetTextureState();
10372 R_SetupShader_DepthOrShadow(false);
10374 RSurf_SetupDepthAndCulling();
10375 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10376 if (rsurface.batchvertex3fbuffer)
10377 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10379 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10383 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10386 for (i = 0;i < numsurfaces;i = j)
10389 surface = rsurface.modelsurfaces + surfacelist[i];
10390 texture = surface->texture;
10391 rsurface.texture = R_GetCurrentTexture(texture);
10392 // scan ahead until we find a different texture
10393 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10394 texturenumsurfaces = 0;
10395 texturesurfacelist[texturenumsurfaces++] = surface;
10396 if(FAKELIGHT_ENABLED)
10398 rsurface.lightmaptexture = NULL;
10399 rsurface.deluxemaptexture = NULL;
10400 rsurface.uselightmaptexture = false;
10401 for (;j < endsurface;j++)
10403 surface = rsurface.modelsurfaces + surfacelist[j];
10404 if (texture != surface->texture)
10406 texturesurfacelist[texturenumsurfaces++] = surface;
10411 rsurface.lightmaptexture = surface->lightmaptexture;
10412 rsurface.deluxemaptexture = surface->deluxemaptexture;
10413 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10414 for (;j < endsurface;j++)
10416 surface = rsurface.modelsurfaces + surfacelist[j];
10417 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10419 texturesurfacelist[texturenumsurfaces++] = surface;
10422 // render the range of surfaces
10423 if (ent == r_refdef.scene.worldentity)
10424 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10426 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10428 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10431 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10433 // transparent surfaces get pushed off into the transparent queue
10434 int surfacelistindex;
10435 const msurface_t *surface;
10436 vec3_t tempcenter, center;
10437 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10439 surface = texturesurfacelist[surfacelistindex];
10440 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10441 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10442 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10443 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10444 if (queueentity->transparent_offset) // transparent offset
10446 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10447 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10448 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10450 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10454 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10456 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10458 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10460 RSurf_SetupDepthAndCulling();
10461 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10462 if (rsurface.batchvertex3fbuffer)
10463 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10465 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10469 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10471 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10474 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10477 if (!rsurface.texture->currentnumlayers)
10479 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10480 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10482 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10484 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10485 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10486 else if (!rsurface.texture->currentnumlayers)
10488 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10490 // in the deferred case, transparent surfaces were queued during prepass
10491 if (!r_shadow_usingdeferredprepass)
10492 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10496 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10497 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10502 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10505 texture_t *texture;
10506 R_FrameData_SetMark();
10507 // break the surface list down into batches by texture and use of lightmapping
10508 for (i = 0;i < numsurfaces;i = j)
10511 // texture is the base texture pointer, rsurface.texture is the
10512 // current frame/skin the texture is directing us to use (for example
10513 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10514 // use skin 1 instead)
10515 texture = surfacelist[i]->texture;
10516 rsurface.texture = R_GetCurrentTexture(texture);
10517 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10519 // if this texture is not the kind we want, skip ahead to the next one
10520 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10524 if(FAKELIGHT_ENABLED || depthonly || prepass)
10526 rsurface.lightmaptexture = NULL;
10527 rsurface.deluxemaptexture = NULL;
10528 rsurface.uselightmaptexture = false;
10529 // simply scan ahead until we find a different texture or lightmap state
10530 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10535 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10536 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10537 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10538 // simply scan ahead until we find a different texture or lightmap state
10539 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10542 // render the range of surfaces
10543 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10545 R_FrameData_ReturnToMark();
10548 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10552 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10555 if (!rsurface.texture->currentnumlayers)
10557 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10558 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10560 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10562 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10563 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10564 else if (!rsurface.texture->currentnumlayers)
10566 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10568 // in the deferred case, transparent surfaces were queued during prepass
10569 if (!r_shadow_usingdeferredprepass)
10570 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10574 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10575 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10580 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10583 texture_t *texture;
10584 R_FrameData_SetMark();
10585 // break the surface list down into batches by texture and use of lightmapping
10586 for (i = 0;i < numsurfaces;i = j)
10589 // texture is the base texture pointer, rsurface.texture is the
10590 // current frame/skin the texture is directing us to use (for example
10591 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10592 // use skin 1 instead)
10593 texture = surfacelist[i]->texture;
10594 rsurface.texture = R_GetCurrentTexture(texture);
10595 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10597 // if this texture is not the kind we want, skip ahead to the next one
10598 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10602 if(FAKELIGHT_ENABLED || depthonly || prepass)
10604 rsurface.lightmaptexture = NULL;
10605 rsurface.deluxemaptexture = NULL;
10606 rsurface.uselightmaptexture = false;
10607 // simply scan ahead until we find a different texture or lightmap state
10608 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10613 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10614 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10615 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10616 // simply scan ahead until we find a different texture or lightmap state
10617 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10620 // render the range of surfaces
10621 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10623 R_FrameData_ReturnToMark();
10626 float locboxvertex3f[6*4*3] =
10628 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10629 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10630 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10631 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10632 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10633 1,0,0, 0,0,0, 0,1,0, 1,1,0
10636 unsigned short locboxelements[6*2*3] =
10641 12,13,14, 12,14,15,
10642 16,17,18, 16,18,19,
10646 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10649 cl_locnode_t *loc = (cl_locnode_t *)ent;
10651 float vertex3f[6*4*3];
10653 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10654 GL_DepthMask(false);
10655 GL_DepthRange(0, 1);
10656 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10657 GL_DepthTest(true);
10658 GL_CullFace(GL_NONE);
10659 R_EntityMatrix(&identitymatrix);
10661 // R_Mesh_ResetTextureState();
10663 i = surfacelist[0];
10664 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10665 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10666 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10667 surfacelist[0] < 0 ? 0.5f : 0.125f);
10669 if (VectorCompare(loc->mins, loc->maxs))
10671 VectorSet(size, 2, 2, 2);
10672 VectorMA(loc->mins, -0.5f, size, mins);
10676 VectorCopy(loc->mins, mins);
10677 VectorSubtract(loc->maxs, loc->mins, size);
10680 for (i = 0;i < 6*4*3;)
10681 for (j = 0;j < 3;j++, i++)
10682 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10684 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10685 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10686 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10689 void R_DrawLocs(void)
10692 cl_locnode_t *loc, *nearestloc;
10694 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10695 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10697 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10698 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10702 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10704 if (decalsystem->decals)
10705 Mem_Free(decalsystem->decals);
10706 memset(decalsystem, 0, sizeof(*decalsystem));
10709 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)
10712 tridecal_t *decals;
10715 // expand or initialize the system
10716 if (decalsystem->maxdecals <= decalsystem->numdecals)
10718 decalsystem_t old = *decalsystem;
10719 qboolean useshortelements;
10720 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10721 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10722 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)));
10723 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10724 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10725 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10726 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10727 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10728 if (decalsystem->numdecals)
10729 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10731 Mem_Free(old.decals);
10732 for (i = 0;i < decalsystem->maxdecals*3;i++)
10733 decalsystem->element3i[i] = i;
10734 if (useshortelements)
10735 for (i = 0;i < decalsystem->maxdecals*3;i++)
10736 decalsystem->element3s[i] = i;
10739 // grab a decal and search for another free slot for the next one
10740 decals = decalsystem->decals;
10741 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10742 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10744 decalsystem->freedecal = i;
10745 if (decalsystem->numdecals <= i)
10746 decalsystem->numdecals = i + 1;
10748 // initialize the decal
10750 decal->triangleindex = triangleindex;
10751 decal->surfaceindex = surfaceindex;
10752 decal->decalsequence = decalsequence;
10753 decal->color4f[0][0] = c0[0];
10754 decal->color4f[0][1] = c0[1];
10755 decal->color4f[0][2] = c0[2];
10756 decal->color4f[0][3] = 1;
10757 decal->color4f[1][0] = c1[0];
10758 decal->color4f[1][1] = c1[1];
10759 decal->color4f[1][2] = c1[2];
10760 decal->color4f[1][3] = 1;
10761 decal->color4f[2][0] = c2[0];
10762 decal->color4f[2][1] = c2[1];
10763 decal->color4f[2][2] = c2[2];
10764 decal->color4f[2][3] = 1;
10765 decal->vertex3f[0][0] = v0[0];
10766 decal->vertex3f[0][1] = v0[1];
10767 decal->vertex3f[0][2] = v0[2];
10768 decal->vertex3f[1][0] = v1[0];
10769 decal->vertex3f[1][1] = v1[1];
10770 decal->vertex3f[1][2] = v1[2];
10771 decal->vertex3f[2][0] = v2[0];
10772 decal->vertex3f[2][1] = v2[1];
10773 decal->vertex3f[2][2] = v2[2];
10774 decal->texcoord2f[0][0] = t0[0];
10775 decal->texcoord2f[0][1] = t0[1];
10776 decal->texcoord2f[1][0] = t1[0];
10777 decal->texcoord2f[1][1] = t1[1];
10778 decal->texcoord2f[2][0] = t2[0];
10779 decal->texcoord2f[2][1] = t2[1];
10780 TriangleNormal(v0, v1, v2, decal->plane);
10781 VectorNormalize(decal->plane);
10782 decal->plane[3] = DotProduct(v0, decal->plane);
10785 extern cvar_t cl_decals_bias;
10786 extern cvar_t cl_decals_models;
10787 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10788 // baseparms, parms, temps
10789 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)
10794 const float *vertex3f;
10795 const float *normal3f;
10797 float points[2][9][3];
10804 e = rsurface.modelelement3i + 3*triangleindex;
10806 vertex3f = rsurface.modelvertex3f;
10807 normal3f = rsurface.modelnormal3f;
10811 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10813 index = 3*e[cornerindex];
10814 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10819 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10821 index = 3*e[cornerindex];
10822 VectorCopy(vertex3f + index, v[cornerindex]);
10827 //TriangleNormal(v[0], v[1], v[2], normal);
10828 //if (DotProduct(normal, localnormal) < 0.0f)
10830 // clip by each of the box planes formed from the projection matrix
10831 // if anything survives, we emit the decal
10832 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]);
10835 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]);
10838 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]);
10841 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]);
10844 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]);
10847 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]);
10850 // some part of the triangle survived, so we have to accept it...
10853 // dynamic always uses the original triangle
10855 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10857 index = 3*e[cornerindex];
10858 VectorCopy(vertex3f + index, v[cornerindex]);
10861 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10863 // convert vertex positions to texcoords
10864 Matrix4x4_Transform(projection, v[cornerindex], temp);
10865 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10866 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10867 // calculate distance fade from the projection origin
10868 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10869 f = bound(0.0f, f, 1.0f);
10870 c[cornerindex][0] = r * f;
10871 c[cornerindex][1] = g * f;
10872 c[cornerindex][2] = b * f;
10873 c[cornerindex][3] = 1.0f;
10874 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10877 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);
10879 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10880 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);
10882 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)
10884 matrix4x4_t projection;
10885 decalsystem_t *decalsystem;
10888 const msurface_t *surface;
10889 const msurface_t *surfaces;
10890 const int *surfacelist;
10891 const texture_t *texture;
10893 int numsurfacelist;
10894 int surfacelistindex;
10897 float localorigin[3];
10898 float localnormal[3];
10899 float localmins[3];
10900 float localmaxs[3];
10903 float planes[6][4];
10906 int bih_triangles_count;
10907 int bih_triangles[256];
10908 int bih_surfaces[256];
10910 decalsystem = &ent->decalsystem;
10911 model = ent->model;
10912 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10914 R_DecalSystem_Reset(&ent->decalsystem);
10918 if (!model->brush.data_leafs && !cl_decals_models.integer)
10920 if (decalsystem->model)
10921 R_DecalSystem_Reset(decalsystem);
10925 if (decalsystem->model != model)
10926 R_DecalSystem_Reset(decalsystem);
10927 decalsystem->model = model;
10929 RSurf_ActiveModelEntity(ent, true, false, false);
10931 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10932 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10933 VectorNormalize(localnormal);
10934 localsize = worldsize*rsurface.inversematrixscale;
10935 localmins[0] = localorigin[0] - localsize;
10936 localmins[1] = localorigin[1] - localsize;
10937 localmins[2] = localorigin[2] - localsize;
10938 localmaxs[0] = localorigin[0] + localsize;
10939 localmaxs[1] = localorigin[1] + localsize;
10940 localmaxs[2] = localorigin[2] + localsize;
10942 //VectorCopy(localnormal, planes[4]);
10943 //VectorVectors(planes[4], planes[2], planes[0]);
10944 AnglesFromVectors(angles, localnormal, NULL, false);
10945 AngleVectors(angles, planes[0], planes[2], planes[4]);
10946 VectorNegate(planes[0], planes[1]);
10947 VectorNegate(planes[2], planes[3]);
10948 VectorNegate(planes[4], planes[5]);
10949 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10950 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10951 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10952 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10953 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10954 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10959 matrix4x4_t forwardprojection;
10960 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10961 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10966 float projectionvector[4][3];
10967 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10968 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10969 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10970 projectionvector[0][0] = planes[0][0] * ilocalsize;
10971 projectionvector[0][1] = planes[1][0] * ilocalsize;
10972 projectionvector[0][2] = planes[2][0] * ilocalsize;
10973 projectionvector[1][0] = planes[0][1] * ilocalsize;
10974 projectionvector[1][1] = planes[1][1] * ilocalsize;
10975 projectionvector[1][2] = planes[2][1] * ilocalsize;
10976 projectionvector[2][0] = planes[0][2] * ilocalsize;
10977 projectionvector[2][1] = planes[1][2] * ilocalsize;
10978 projectionvector[2][2] = planes[2][2] * ilocalsize;
10979 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10980 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10981 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10982 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10986 dynamic = model->surfmesh.isanimated;
10987 numsurfacelist = model->nummodelsurfaces;
10988 surfacelist = model->sortedmodelsurfaces;
10989 surfaces = model->data_surfaces;
10992 bih_triangles_count = -1;
10995 if(model->render_bih.numleafs)
10996 bih = &model->render_bih;
10997 else if(model->collision_bih.numleafs)
10998 bih = &model->collision_bih;
11001 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11002 if(bih_triangles_count == 0)
11004 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11006 if(bih_triangles_count > 0)
11008 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11010 surfaceindex = bih_surfaces[triangleindex];
11011 surface = surfaces + surfaceindex;
11012 texture = surface->texture;
11013 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11015 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11017 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11022 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11024 surfaceindex = surfacelist[surfacelistindex];
11025 surface = surfaces + surfaceindex;
11026 // check cull box first because it rejects more than any other check
11027 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11029 // skip transparent surfaces
11030 texture = surface->texture;
11031 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11033 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11035 numtriangles = surface->num_triangles;
11036 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11037 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11042 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11043 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)
11045 int renderentityindex;
11046 float worldmins[3];
11047 float worldmaxs[3];
11048 entity_render_t *ent;
11050 if (!cl_decals_newsystem.integer)
11053 worldmins[0] = worldorigin[0] - worldsize;
11054 worldmins[1] = worldorigin[1] - worldsize;
11055 worldmins[2] = worldorigin[2] - worldsize;
11056 worldmaxs[0] = worldorigin[0] + worldsize;
11057 worldmaxs[1] = worldorigin[1] + worldsize;
11058 worldmaxs[2] = worldorigin[2] + worldsize;
11060 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11062 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11064 ent = r_refdef.scene.entities[renderentityindex];
11065 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11068 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11072 typedef struct r_decalsystem_splatqueue_s
11074 vec3_t worldorigin;
11075 vec3_t worldnormal;
11081 r_decalsystem_splatqueue_t;
11083 int r_decalsystem_numqueued = 0;
11084 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11086 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)
11088 r_decalsystem_splatqueue_t *queue;
11090 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11093 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11094 VectorCopy(worldorigin, queue->worldorigin);
11095 VectorCopy(worldnormal, queue->worldnormal);
11096 Vector4Set(queue->color, r, g, b, a);
11097 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11098 queue->worldsize = worldsize;
11099 queue->decalsequence = cl.decalsequence++;
11102 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11105 r_decalsystem_splatqueue_t *queue;
11107 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11108 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);
11109 r_decalsystem_numqueued = 0;
11112 extern cvar_t cl_decals_max;
11113 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11116 decalsystem_t *decalsystem = &ent->decalsystem;
11123 if (!decalsystem->numdecals)
11126 if (r_showsurfaces.integer)
11129 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11131 R_DecalSystem_Reset(decalsystem);
11135 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11136 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11138 if (decalsystem->lastupdatetime)
11139 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11142 decalsystem->lastupdatetime = r_refdef.scene.time;
11143 decal = decalsystem->decals;
11144 numdecals = decalsystem->numdecals;
11146 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11148 if (decal->color4f[0][3])
11150 decal->lived += frametime;
11151 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11153 memset(decal, 0, sizeof(*decal));
11154 if (decalsystem->freedecal > i)
11155 decalsystem->freedecal = i;
11159 decal = decalsystem->decals;
11160 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11163 // collapse the array by shuffling the tail decals into the gaps
11166 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11167 decalsystem->freedecal++;
11168 if (decalsystem->freedecal == numdecals)
11170 decal[decalsystem->freedecal] = decal[--numdecals];
11173 decalsystem->numdecals = numdecals;
11175 if (numdecals <= 0)
11177 // if there are no decals left, reset decalsystem
11178 R_DecalSystem_Reset(decalsystem);
11182 extern skinframe_t *decalskinframe;
11183 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11186 decalsystem_t *decalsystem = &ent->decalsystem;
11195 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11198 numdecals = decalsystem->numdecals;
11202 if (r_showsurfaces.integer)
11205 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11207 R_DecalSystem_Reset(decalsystem);
11211 // if the model is static it doesn't matter what value we give for
11212 // wantnormals and wanttangents, so this logic uses only rules applicable
11213 // to a model, knowing that they are meaningless otherwise
11214 if (ent == r_refdef.scene.worldentity)
11215 RSurf_ActiveWorldEntity();
11217 RSurf_ActiveModelEntity(ent, false, false, false);
11219 decalsystem->lastupdatetime = r_refdef.scene.time;
11220 decal = decalsystem->decals;
11222 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11224 // update vertex positions for animated models
11225 v3f = decalsystem->vertex3f;
11226 c4f = decalsystem->color4f;
11227 t2f = decalsystem->texcoord2f;
11228 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11230 if (!decal->color4f[0][3])
11233 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11237 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11240 // update color values for fading decals
11241 if (decal->lived >= cl_decals_time.value)
11242 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11246 c4f[ 0] = decal->color4f[0][0] * alpha;
11247 c4f[ 1] = decal->color4f[0][1] * alpha;
11248 c4f[ 2] = decal->color4f[0][2] * alpha;
11250 c4f[ 4] = decal->color4f[1][0] * alpha;
11251 c4f[ 5] = decal->color4f[1][1] * alpha;
11252 c4f[ 6] = decal->color4f[1][2] * alpha;
11254 c4f[ 8] = decal->color4f[2][0] * alpha;
11255 c4f[ 9] = decal->color4f[2][1] * alpha;
11256 c4f[10] = decal->color4f[2][2] * alpha;
11259 t2f[0] = decal->texcoord2f[0][0];
11260 t2f[1] = decal->texcoord2f[0][1];
11261 t2f[2] = decal->texcoord2f[1][0];
11262 t2f[3] = decal->texcoord2f[1][1];
11263 t2f[4] = decal->texcoord2f[2][0];
11264 t2f[5] = decal->texcoord2f[2][1];
11266 // update vertex positions for animated models
11267 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11269 e = rsurface.modelelement3i + 3*decal->triangleindex;
11270 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11271 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11272 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11276 VectorCopy(decal->vertex3f[0], v3f);
11277 VectorCopy(decal->vertex3f[1], v3f + 3);
11278 VectorCopy(decal->vertex3f[2], v3f + 6);
11281 if (r_refdef.fogenabled)
11283 alpha = RSurf_FogVertex(v3f);
11284 VectorScale(c4f, alpha, c4f);
11285 alpha = RSurf_FogVertex(v3f + 3);
11286 VectorScale(c4f + 4, alpha, c4f + 4);
11287 alpha = RSurf_FogVertex(v3f + 6);
11288 VectorScale(c4f + 8, alpha, c4f + 8);
11299 r_refdef.stats.drawndecals += numtris;
11301 // now render the decals all at once
11302 // (this assumes they all use one particle font texture!)
11303 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);
11304 // R_Mesh_ResetTextureState();
11305 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11306 GL_DepthMask(false);
11307 GL_DepthRange(0, 1);
11308 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11309 GL_DepthTest(true);
11310 GL_CullFace(GL_NONE);
11311 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11312 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11313 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11317 static void R_DrawModelDecals(void)
11321 // fade faster when there are too many decals
11322 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11323 for (i = 0;i < r_refdef.scene.numentities;i++)
11324 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11326 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11327 for (i = 0;i < r_refdef.scene.numentities;i++)
11328 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11329 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11331 R_DecalSystem_ApplySplatEntitiesQueue();
11333 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11334 for (i = 0;i < r_refdef.scene.numentities;i++)
11335 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11337 r_refdef.stats.totaldecals += numdecals;
11339 if (r_showsurfaces.integer)
11342 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11344 for (i = 0;i < r_refdef.scene.numentities;i++)
11346 if (!r_refdef.viewcache.entityvisible[i])
11348 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11349 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11353 extern cvar_t mod_collision_bih;
11354 void R_DrawDebugModel(void)
11356 entity_render_t *ent = rsurface.entity;
11357 int i, j, k, l, flagsmask;
11358 const msurface_t *surface;
11359 dp_model_t *model = ent->model;
11362 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11365 if (r_showoverdraw.value > 0)
11367 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11368 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11369 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11370 GL_DepthTest(false);
11371 GL_DepthMask(false);
11372 GL_DepthRange(0, 1);
11373 GL_BlendFunc(GL_ONE, GL_ONE);
11374 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11376 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11378 rsurface.texture = R_GetCurrentTexture(surface->texture);
11379 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11381 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11382 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11383 if (!rsurface.texture->currentlayers->depthmask)
11384 GL_Color(c, 0, 0, 1.0f);
11385 else if (ent == r_refdef.scene.worldentity)
11386 GL_Color(c, c, c, 1.0f);
11388 GL_Color(0, c, 0, 1.0f);
11389 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11393 rsurface.texture = NULL;
11396 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11398 // R_Mesh_ResetTextureState();
11399 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11400 GL_DepthRange(0, 1);
11401 GL_DepthTest(!r_showdisabledepthtest.integer);
11402 GL_DepthMask(false);
11403 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11405 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11409 qboolean cullbox = ent == r_refdef.scene.worldentity;
11410 const q3mbrush_t *brush;
11411 const bih_t *bih = &model->collision_bih;
11412 const bih_leaf_t *bihleaf;
11413 float vertex3f[3][3];
11414 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11416 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11418 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11420 switch (bihleaf->type)
11423 brush = model->brush.data_brushes + bihleaf->itemindex;
11424 if (brush->colbrushf && brush->colbrushf->numtriangles)
11426 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);
11427 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11428 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11431 case BIH_COLLISIONTRIANGLE:
11432 triangleindex = bihleaf->itemindex;
11433 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11434 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11435 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11436 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);
11437 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11438 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11440 case BIH_RENDERTRIANGLE:
11441 triangleindex = bihleaf->itemindex;
11442 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11443 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11444 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11445 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);
11446 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11447 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11453 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11456 if (r_showtris.integer && qglPolygonMode)
11458 if (r_showdisabledepthtest.integer)
11460 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11461 GL_DepthMask(false);
11465 GL_BlendFunc(GL_ONE, GL_ZERO);
11466 GL_DepthMask(true);
11468 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11469 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11471 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11473 rsurface.texture = R_GetCurrentTexture(surface->texture);
11474 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11476 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11477 if (!rsurface.texture->currentlayers->depthmask)
11478 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11479 else if (ent == r_refdef.scene.worldentity)
11480 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11482 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11483 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11487 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11488 rsurface.texture = NULL;
11491 if (r_shownormals.value != 0 && qglBegin)
11493 if (r_showdisabledepthtest.integer)
11495 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11496 GL_DepthMask(false);
11500 GL_BlendFunc(GL_ONE, GL_ZERO);
11501 GL_DepthMask(true);
11503 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11505 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11507 rsurface.texture = R_GetCurrentTexture(surface->texture);
11508 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11510 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11511 qglBegin(GL_LINES);
11512 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11514 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11516 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11517 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11518 qglVertex3f(v[0], v[1], v[2]);
11519 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11520 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11521 qglVertex3f(v[0], v[1], v[2]);
11524 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11526 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11528 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11529 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11530 qglVertex3f(v[0], v[1], v[2]);
11531 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11532 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11533 qglVertex3f(v[0], v[1], v[2]);
11536 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11538 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11540 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11541 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11542 qglVertex3f(v[0], v[1], v[2]);
11543 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11544 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11545 qglVertex3f(v[0], v[1], v[2]);
11548 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11550 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11552 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11553 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11554 qglVertex3f(v[0], v[1], v[2]);
11555 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11556 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11557 qglVertex3f(v[0], v[1], v[2]);
11564 rsurface.texture = NULL;
11569 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11570 int r_maxsurfacelist = 0;
11571 const msurface_t **r_surfacelist = NULL;
11572 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11574 int i, j, endj, flagsmask;
11575 dp_model_t *model = r_refdef.scene.worldmodel;
11576 msurface_t *surfaces;
11577 unsigned char *update;
11578 int numsurfacelist = 0;
11582 if (r_maxsurfacelist < model->num_surfaces)
11584 r_maxsurfacelist = model->num_surfaces;
11586 Mem_Free((msurface_t**)r_surfacelist);
11587 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11590 RSurf_ActiveWorldEntity();
11592 surfaces = model->data_surfaces;
11593 update = model->brushq1.lightmapupdateflags;
11595 // update light styles on this submodel
11596 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11598 model_brush_lightstyleinfo_t *style;
11599 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11601 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11603 int *list = style->surfacelist;
11604 style->value = r_refdef.scene.lightstylevalue[style->style];
11605 for (j = 0;j < style->numsurfaces;j++)
11606 update[list[j]] = true;
11611 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11615 R_DrawDebugModel();
11616 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11620 rsurface.lightmaptexture = NULL;
11621 rsurface.deluxemaptexture = NULL;
11622 rsurface.uselightmaptexture = false;
11623 rsurface.texture = NULL;
11624 rsurface.rtlight = NULL;
11625 numsurfacelist = 0;
11626 // add visible surfaces to draw list
11627 for (i = 0;i < model->nummodelsurfaces;i++)
11629 j = model->sortedmodelsurfaces[i];
11630 if (r_refdef.viewcache.world_surfacevisible[j])
11631 r_surfacelist[numsurfacelist++] = surfaces + j;
11633 // update lightmaps if needed
11634 if (model->brushq1.firstrender)
11636 model->brushq1.firstrender = false;
11637 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11639 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11643 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11644 if (r_refdef.viewcache.world_surfacevisible[j])
11646 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11648 // don't do anything if there were no surfaces
11649 if (!numsurfacelist)
11651 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11654 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11656 // add to stats if desired
11657 if (r_speeds.integer && !skysurfaces && !depthonly)
11659 r_refdef.stats.world_surfaces += numsurfacelist;
11660 for (j = 0;j < numsurfacelist;j++)
11661 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11664 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11667 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11669 int i, j, endj, flagsmask;
11670 dp_model_t *model = ent->model;
11671 msurface_t *surfaces;
11672 unsigned char *update;
11673 int numsurfacelist = 0;
11677 if (r_maxsurfacelist < model->num_surfaces)
11679 r_maxsurfacelist = model->num_surfaces;
11681 Mem_Free((msurface_t **)r_surfacelist);
11682 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11685 // if the model is static it doesn't matter what value we give for
11686 // wantnormals and wanttangents, so this logic uses only rules applicable
11687 // to a model, knowing that they are meaningless otherwise
11688 if (ent == r_refdef.scene.worldentity)
11689 RSurf_ActiveWorldEntity();
11690 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11691 RSurf_ActiveModelEntity(ent, false, false, false);
11693 RSurf_ActiveModelEntity(ent, true, true, true);
11694 else if (depthonly)
11696 switch (vid.renderpath)
11698 case RENDERPATH_GL20:
11699 case RENDERPATH_D3D9:
11700 case RENDERPATH_D3D10:
11701 case RENDERPATH_D3D11:
11702 case RENDERPATH_SOFT:
11703 case RENDERPATH_GLES2:
11704 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11706 case RENDERPATH_GL11:
11707 case RENDERPATH_GL13:
11708 case RENDERPATH_GLES1:
11709 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11715 switch (vid.renderpath)
11717 case RENDERPATH_GL20:
11718 case RENDERPATH_D3D9:
11719 case RENDERPATH_D3D10:
11720 case RENDERPATH_D3D11:
11721 case RENDERPATH_SOFT:
11722 case RENDERPATH_GLES2:
11723 RSurf_ActiveModelEntity(ent, true, true, false);
11725 case RENDERPATH_GL11:
11726 case RENDERPATH_GL13:
11727 case RENDERPATH_GLES1:
11728 RSurf_ActiveModelEntity(ent, true, false, false);
11733 surfaces = model->data_surfaces;
11734 update = model->brushq1.lightmapupdateflags;
11736 // update light styles
11737 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11739 model_brush_lightstyleinfo_t *style;
11740 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11742 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11744 int *list = style->surfacelist;
11745 style->value = r_refdef.scene.lightstylevalue[style->style];
11746 for (j = 0;j < style->numsurfaces;j++)
11747 update[list[j]] = true;
11752 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11756 R_DrawDebugModel();
11757 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11761 rsurface.lightmaptexture = NULL;
11762 rsurface.deluxemaptexture = NULL;
11763 rsurface.uselightmaptexture = false;
11764 rsurface.texture = NULL;
11765 rsurface.rtlight = NULL;
11766 numsurfacelist = 0;
11767 // add visible surfaces to draw list
11768 for (i = 0;i < model->nummodelsurfaces;i++)
11769 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11770 // don't do anything if there were no surfaces
11771 if (!numsurfacelist)
11773 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11776 // update lightmaps if needed
11780 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11785 R_BuildLightMap(ent, surfaces + j);
11790 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11792 R_BuildLightMap(ent, surfaces + j);
11793 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11795 // add to stats if desired
11796 if (r_speeds.integer && !skysurfaces && !depthonly)
11798 r_refdef.stats.entities_surfaces += numsurfacelist;
11799 for (j = 0;j < numsurfacelist;j++)
11800 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11803 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11806 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11808 static texture_t texture;
11809 static msurface_t surface;
11810 const msurface_t *surfacelist = &surface;
11812 // fake enough texture and surface state to render this geometry
11814 texture.update_lastrenderframe = -1; // regenerate this texture
11815 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11816 texture.currentskinframe = skinframe;
11817 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11818 texture.offsetmapping = OFFSETMAPPING_OFF;
11819 texture.offsetscale = 1;
11820 texture.specularscalemod = 1;
11821 texture.specularpowermod = 1;
11823 surface.texture = &texture;
11824 surface.num_triangles = numtriangles;
11825 surface.num_firsttriangle = firsttriangle;
11826 surface.num_vertices = numvertices;
11827 surface.num_firstvertex = firstvertex;
11830 rsurface.texture = R_GetCurrentTexture(surface.texture);
11831 rsurface.lightmaptexture = NULL;
11832 rsurface.deluxemaptexture = NULL;
11833 rsurface.uselightmaptexture = false;
11834 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11837 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)
11839 static msurface_t surface;
11840 const msurface_t *surfacelist = &surface;
11842 // fake enough texture and surface state to render this geometry
11843 surface.texture = texture;
11844 surface.num_triangles = numtriangles;
11845 surface.num_firsttriangle = firsttriangle;
11846 surface.num_vertices = numvertices;
11847 surface.num_firstvertex = firstvertex;
11850 rsurface.texture = R_GetCurrentTexture(surface.texture);
11851 rsurface.lightmaptexture = NULL;
11852 rsurface.deluxemaptexture = NULL;
11853 rsurface.uselightmaptexture = false;
11854 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);