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_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
131 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
132 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
134 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
135 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
136 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
137 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
138 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
139 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
140 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
141 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
143 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)"};
144 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"};
146 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
147 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
148 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
150 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"};
151 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"};
152 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
153 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
154 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"};
155 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)"};
156 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)"};
157 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
159 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)"};
160 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
161 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)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
163 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)"};
164 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)"};
165 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
166 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"};
167 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."};
168 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176 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)"};
178 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)"};
179 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
180 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"};
181 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
182 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
183 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
184 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"};
186 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
187 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
188 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
189 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
191 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
192 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
193 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
194 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
195 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
196 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
197 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
199 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
200 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
201 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
202 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)"};
203 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
204 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
205 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
208 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
209 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
211 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"};
213 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"};
215 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
217 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
219 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
220 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"};
222 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."};
224 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)"};
226 extern cvar_t v_glslgamma;
227 extern cvar_t v_glslgamma_2d;
229 extern qboolean v_flipped_state;
231 static struct r_bloomstate_s
236 int bloomwidth, bloomheight;
238 textype_t texturetype;
239 int viewfbo; // used to check if r_viewfbo cvar has changed
241 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
242 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
243 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
245 int screentexturewidth, screentextureheight;
246 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
248 int bloomtexturewidth, bloomtextureheight;
249 rtexture_t *texture_bloom;
251 // arrays for rendering the screen passes
252 float screentexcoord2f[8];
253 float bloomtexcoord2f[8];
254 float offsettexcoord2f[8];
256 r_viewport_t viewport;
260 r_waterstate_t r_waterstate;
262 /// shadow volume bsp struct with automatically growing nodes buffer
265 rtexture_t *r_texture_blanknormalmap;
266 rtexture_t *r_texture_white;
267 rtexture_t *r_texture_grey128;
268 rtexture_t *r_texture_black;
269 rtexture_t *r_texture_notexture;
270 rtexture_t *r_texture_whitecube;
271 rtexture_t *r_texture_normalizationcube;
272 rtexture_t *r_texture_fogattenuation;
273 rtexture_t *r_texture_fogheighttexture;
274 rtexture_t *r_texture_gammaramps;
275 unsigned int r_texture_gammaramps_serial;
276 //rtexture_t *r_texture_fogintensity;
277 rtexture_t *r_texture_reflectcube;
279 // TODO: hash lookups?
280 typedef struct cubemapinfo_s
287 int r_texture_numcubemaps;
288 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
290 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
291 unsigned int r_numqueries;
292 unsigned int r_maxqueries;
294 typedef struct r_qwskincache_s
296 char name[MAX_QPATH];
297 skinframe_t *skinframe;
301 static r_qwskincache_t *r_qwskincache;
302 static int r_qwskincache_size;
304 /// vertex coordinates for a quad that covers the screen exactly
305 extern const float r_screenvertex3f[12];
306 extern const float r_d3dscreenvertex3f[12];
307 const float r_screenvertex3f[12] =
314 const float r_d3dscreenvertex3f[12] =
322 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
325 for (i = 0;i < verts;i++)
336 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
339 for (i = 0;i < verts;i++)
349 // FIXME: move this to client?
352 if (gamemode == GAME_NEHAHRA)
354 Cvar_Set("gl_fogenable", "0");
355 Cvar_Set("gl_fogdensity", "0.2");
356 Cvar_Set("gl_fogred", "0.3");
357 Cvar_Set("gl_foggreen", "0.3");
358 Cvar_Set("gl_fogblue", "0.3");
360 r_refdef.fog_density = 0;
361 r_refdef.fog_red = 0;
362 r_refdef.fog_green = 0;
363 r_refdef.fog_blue = 0;
364 r_refdef.fog_alpha = 1;
365 r_refdef.fog_start = 0;
366 r_refdef.fog_end = 16384;
367 r_refdef.fog_height = 1<<30;
368 r_refdef.fog_fadedepth = 128;
369 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
372 static void R_BuildBlankTextures(void)
374 unsigned char data[4];
375 data[2] = 128; // normal X
376 data[1] = 128; // normal Y
377 data[0] = 255; // normal Z
378 data[3] = 128; // height
379 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397 static void R_BuildNoTexture(void)
400 unsigned char pix[16][16][4];
401 // this makes a light grey/dark grey checkerboard texture
402 for (y = 0;y < 16;y++)
404 for (x = 0;x < 16;x++)
406 if ((y < 8) ^ (x < 8))
422 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
425 static void R_BuildWhiteCube(void)
427 unsigned char data[6*1*1*4];
428 memset(data, 255, sizeof(data));
429 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
432 static void R_BuildNormalizationCube(void)
436 vec_t s, t, intensity;
439 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
440 for (side = 0;side < 6;side++)
442 for (y = 0;y < NORMSIZE;y++)
444 for (x = 0;x < NORMSIZE;x++)
446 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
482 intensity = 127.0f / sqrt(DotProduct(v, v));
483 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
484 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
485 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
486 data[((side*64+y)*64+x)*4+3] = 255;
490 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
494 static void R_BuildFogTexture(void)
498 unsigned char data1[FOGWIDTH][4];
499 //unsigned char data2[FOGWIDTH][4];
502 r_refdef.fogmasktable_start = r_refdef.fog_start;
503 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
504 r_refdef.fogmasktable_range = r_refdef.fogrange;
505 r_refdef.fogmasktable_density = r_refdef.fog_density;
507 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
508 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
510 d = (x * r - r_refdef.fogmasktable_start);
511 if(developer_extra.integer)
512 Con_DPrintf("%f ", d);
514 if (r_fog_exp2.integer)
515 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
517 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
518 if(developer_extra.integer)
519 Con_DPrintf(" : %f ", alpha);
520 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
521 if(developer_extra.integer)
522 Con_DPrintf(" = %f\n", alpha);
523 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
526 for (x = 0;x < FOGWIDTH;x++)
528 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
533 //data2[x][0] = 255 - b;
534 //data2[x][1] = 255 - b;
535 //data2[x][2] = 255 - b;
538 if (r_texture_fogattenuation)
540 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
545 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
546 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
550 static void R_BuildFogHeightTexture(void)
552 unsigned char *inpixels;
560 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
561 if (r_refdef.fogheighttexturename[0])
562 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
565 r_refdef.fog_height_tablesize = 0;
566 if (r_texture_fogheighttexture)
567 R_FreeTexture(r_texture_fogheighttexture);
568 r_texture_fogheighttexture = NULL;
569 if (r_refdef.fog_height_table2d)
570 Mem_Free(r_refdef.fog_height_table2d);
571 r_refdef.fog_height_table2d = NULL;
572 if (r_refdef.fog_height_table1d)
573 Mem_Free(r_refdef.fog_height_table1d);
574 r_refdef.fog_height_table1d = NULL;
578 r_refdef.fog_height_tablesize = size;
579 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
580 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
581 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
583 // LordHavoc: now the magic - what is that table2d for? it is a cooked
584 // average fog color table accounting for every fog layer between a point
585 // and the camera. (Note: attenuation is handled separately!)
586 for (y = 0;y < size;y++)
588 for (x = 0;x < size;x++)
594 for (j = x;j <= y;j++)
596 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
602 for (j = x;j >= y;j--)
604 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
609 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
610 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
611 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
612 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
615 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
618 //=======================================================================================================================================================
620 static const char *builtinshaderstring =
621 #include "shader_glsl.h"
624 const char *builtinhlslshaderstring =
625 #include "shader_hlsl.h"
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
631 //=======================================================================================================================================================
633 typedef struct shaderpermutationinfo_s
638 shaderpermutationinfo_t;
640 typedef struct shadermodeinfo_s
642 const char *vertexfilename;
643 const char *geometryfilename;
644 const char *fragmentfilename;
650 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
651 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
653 {"#define USEDIFFUSE\n", " diffuse"},
654 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
655 {"#define USEVIEWTINT\n", " viewtint"},
656 {"#define USECOLORMAPPING\n", " colormapping"},
657 {"#define USESATURATION\n", " saturation"},
658 {"#define USEFOGINSIDE\n", " foginside"},
659 {"#define USEFOGOUTSIDE\n", " fogoutside"},
660 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
661 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
662 {"#define USEGAMMARAMPS\n", " gammaramps"},
663 {"#define USECUBEFILTER\n", " cubefilter"},
664 {"#define USEGLOW\n", " glow"},
665 {"#define USEBLOOM\n", " bloom"},
666 {"#define USESPECULAR\n", " specular"},
667 {"#define USEPOSTPROCESSING\n", " postprocessing"},
668 {"#define USEREFLECTION\n", " reflection"},
669 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
670 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
671 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
672 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
673 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
674 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
675 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
676 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
677 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
678 {"#define USEALPHAKILL\n", " alphakill"},
679 {"#define USEREFLECTCUBE\n", " reflectcube"},
680 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
681 {"#define USEBOUNCEGRID\n", " bouncegrid"},
682 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
683 {"#define USETRIPPY\n", " trippy"},
686 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
687 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
704 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
705 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
706 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
709 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
720 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
721 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
723 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
724 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
725 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
726 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
727 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
728 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
731 struct r_glsl_permutation_s;
732 typedef struct r_glsl_permutation_s
735 struct r_glsl_permutation_s *hashnext;
737 unsigned int permutation;
739 /// indicates if we have tried compiling this permutation already
741 /// 0 if compilation failed
743 // texture units assigned to each detected uniform
744 int tex_Texture_First;
745 int tex_Texture_Second;
746 int tex_Texture_GammaRamps;
747 int tex_Texture_Normal;
748 int tex_Texture_Color;
749 int tex_Texture_Gloss;
750 int tex_Texture_Glow;
751 int tex_Texture_SecondaryNormal;
752 int tex_Texture_SecondaryColor;
753 int tex_Texture_SecondaryGloss;
754 int tex_Texture_SecondaryGlow;
755 int tex_Texture_Pants;
756 int tex_Texture_Shirt;
757 int tex_Texture_FogHeightTexture;
758 int tex_Texture_FogMask;
759 int tex_Texture_Lightmap;
760 int tex_Texture_Deluxemap;
761 int tex_Texture_Attenuation;
762 int tex_Texture_Cube;
763 int tex_Texture_Refraction;
764 int tex_Texture_Reflection;
765 int tex_Texture_ShadowMap2D;
766 int tex_Texture_CubeProjection;
767 int tex_Texture_ScreenDepth;
768 int tex_Texture_ScreenNormalMap;
769 int tex_Texture_ScreenDiffuse;
770 int tex_Texture_ScreenSpecular;
771 int tex_Texture_ReflectMask;
772 int tex_Texture_ReflectCube;
773 int tex_Texture_BounceGrid;
774 /// locations of detected uniforms in program object, or -1 if not found
775 int loc_Texture_First;
776 int loc_Texture_Second;
777 int loc_Texture_GammaRamps;
778 int loc_Texture_Normal;
779 int loc_Texture_Color;
780 int loc_Texture_Gloss;
781 int loc_Texture_Glow;
782 int loc_Texture_SecondaryNormal;
783 int loc_Texture_SecondaryColor;
784 int loc_Texture_SecondaryGloss;
785 int loc_Texture_SecondaryGlow;
786 int loc_Texture_Pants;
787 int loc_Texture_Shirt;
788 int loc_Texture_FogHeightTexture;
789 int loc_Texture_FogMask;
790 int loc_Texture_Lightmap;
791 int loc_Texture_Deluxemap;
792 int loc_Texture_Attenuation;
793 int loc_Texture_Cube;
794 int loc_Texture_Refraction;
795 int loc_Texture_Reflection;
796 int loc_Texture_ShadowMap2D;
797 int loc_Texture_CubeProjection;
798 int loc_Texture_ScreenDepth;
799 int loc_Texture_ScreenNormalMap;
800 int loc_Texture_ScreenDiffuse;
801 int loc_Texture_ScreenSpecular;
802 int loc_Texture_ReflectMask;
803 int loc_Texture_ReflectCube;
804 int loc_Texture_BounceGrid;
806 int loc_BloomBlur_Parameters;
808 int loc_Color_Ambient;
809 int loc_Color_Diffuse;
810 int loc_Color_Specular;
814 int loc_DeferredColor_Ambient;
815 int loc_DeferredColor_Diffuse;
816 int loc_DeferredColor_Specular;
817 int loc_DeferredMod_Diffuse;
818 int loc_DeferredMod_Specular;
819 int loc_DistortScaleRefractReflect;
822 int loc_FogHeightFade;
824 int loc_FogPlaneViewDist;
825 int loc_FogRangeRecip;
828 int loc_LightPosition;
829 int loc_OffsetMapping_ScaleSteps;
830 int loc_OffsetMapping_LodDistance;
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_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1154 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1155 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1156 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1157 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1158 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1159 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1160 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1161 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1162 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1163 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1164 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1165 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1166 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1167 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1168 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1169 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1170 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1171 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1172 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1173 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1174 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1175 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1176 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1177 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1178 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1179 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1180 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1181 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1182 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1183 // initialize the samplers to refer to the texture units we use
1184 p->tex_Texture_First = -1;
1185 p->tex_Texture_Second = -1;
1186 p->tex_Texture_GammaRamps = -1;
1187 p->tex_Texture_Normal = -1;
1188 p->tex_Texture_Color = -1;
1189 p->tex_Texture_Gloss = -1;
1190 p->tex_Texture_Glow = -1;
1191 p->tex_Texture_SecondaryNormal = -1;
1192 p->tex_Texture_SecondaryColor = -1;
1193 p->tex_Texture_SecondaryGloss = -1;
1194 p->tex_Texture_SecondaryGlow = -1;
1195 p->tex_Texture_Pants = -1;
1196 p->tex_Texture_Shirt = -1;
1197 p->tex_Texture_FogHeightTexture = -1;
1198 p->tex_Texture_FogMask = -1;
1199 p->tex_Texture_Lightmap = -1;
1200 p->tex_Texture_Deluxemap = -1;
1201 p->tex_Texture_Attenuation = -1;
1202 p->tex_Texture_Cube = -1;
1203 p->tex_Texture_Refraction = -1;
1204 p->tex_Texture_Reflection = -1;
1205 p->tex_Texture_ShadowMap2D = -1;
1206 p->tex_Texture_CubeProjection = -1;
1207 p->tex_Texture_ScreenDepth = -1;
1208 p->tex_Texture_ScreenNormalMap = -1;
1209 p->tex_Texture_ScreenDiffuse = -1;
1210 p->tex_Texture_ScreenSpecular = -1;
1211 p->tex_Texture_ReflectMask = -1;
1212 p->tex_Texture_ReflectCube = -1;
1213 p->tex_Texture_BounceGrid = -1;
1215 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1216 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1217 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1218 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1219 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1220 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1221 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1222 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1223 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1224 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1225 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1226 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1227 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1228 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1229 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1230 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1231 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1232 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1233 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1234 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1235 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1236 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1237 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1238 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1239 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1240 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1241 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1242 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1243 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1244 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1246 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1249 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1253 Mem_Free(vertexstring);
1255 Mem_Free(geometrystring);
1257 Mem_Free(fragmentstring);
1260 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1262 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1263 if (r_glsl_permutation != perm)
1265 r_glsl_permutation = perm;
1266 if (!r_glsl_permutation->program)
1268 if (!r_glsl_permutation->compiled)
1269 R_GLSL_CompilePermutation(perm, mode, permutation);
1270 if (!r_glsl_permutation->program)
1272 // remove features until we find a valid permutation
1274 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1276 // reduce i more quickly whenever it would not remove any bits
1277 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1278 if (!(permutation & j))
1281 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282 if (!r_glsl_permutation->compiled)
1283 R_GLSL_CompilePermutation(perm, mode, permutation);
1284 if (r_glsl_permutation->program)
1287 if (i >= SHADERPERMUTATION_COUNT)
1289 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1290 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1291 qglUseProgram(0);CHECKGLERROR
1292 return; // no bit left to clear, entire mode is broken
1297 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1299 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1300 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1301 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1308 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1309 extern D3DCAPS9 vid_d3d9caps;
1312 struct r_hlsl_permutation_s;
1313 typedef struct r_hlsl_permutation_s
1315 /// hash lookup data
1316 struct r_hlsl_permutation_s *hashnext;
1318 unsigned int permutation;
1320 /// indicates if we have tried compiling this permutation already
1322 /// NULL if compilation failed
1323 IDirect3DVertexShader9 *vertexshader;
1324 IDirect3DPixelShader9 *pixelshader;
1326 r_hlsl_permutation_t;
1328 typedef enum D3DVSREGISTER_e
1330 D3DVSREGISTER_TexMatrix = 0, // float4x4
1331 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1332 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1333 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1334 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1335 D3DVSREGISTER_ModelToLight = 20, // float4x4
1336 D3DVSREGISTER_EyePosition = 24,
1337 D3DVSREGISTER_FogPlane = 25,
1338 D3DVSREGISTER_LightDir = 26,
1339 D3DVSREGISTER_LightPosition = 27,
1343 typedef enum D3DPSREGISTER_e
1345 D3DPSREGISTER_Alpha = 0,
1346 D3DPSREGISTER_BloomBlur_Parameters = 1,
1347 D3DPSREGISTER_ClientTime = 2,
1348 D3DPSREGISTER_Color_Ambient = 3,
1349 D3DPSREGISTER_Color_Diffuse = 4,
1350 D3DPSREGISTER_Color_Specular = 5,
1351 D3DPSREGISTER_Color_Glow = 6,
1352 D3DPSREGISTER_Color_Pants = 7,
1353 D3DPSREGISTER_Color_Shirt = 8,
1354 D3DPSREGISTER_DeferredColor_Ambient = 9,
1355 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1356 D3DPSREGISTER_DeferredColor_Specular = 11,
1357 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1358 D3DPSREGISTER_DeferredMod_Specular = 13,
1359 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1360 D3DPSREGISTER_EyePosition = 15, // unused
1361 D3DPSREGISTER_FogColor = 16,
1362 D3DPSREGISTER_FogHeightFade = 17,
1363 D3DPSREGISTER_FogPlane = 18,
1364 D3DPSREGISTER_FogPlaneViewDist = 19,
1365 D3DPSREGISTER_FogRangeRecip = 20,
1366 D3DPSREGISTER_LightColor = 21,
1367 D3DPSREGISTER_LightDir = 22, // unused
1368 D3DPSREGISTER_LightPosition = 23,
1369 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1370 D3DPSREGISTER_PixelSize = 25,
1371 D3DPSREGISTER_ReflectColor = 26,
1372 D3DPSREGISTER_ReflectFactor = 27,
1373 D3DPSREGISTER_ReflectOffset = 28,
1374 D3DPSREGISTER_RefractColor = 29,
1375 D3DPSREGISTER_Saturation = 30,
1376 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1377 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1378 D3DPSREGISTER_ScreenToDepth = 33,
1379 D3DPSREGISTER_ShadowMap_Parameters = 34,
1380 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1381 D3DPSREGISTER_SpecularPower = 36,
1382 D3DPSREGISTER_UserVec1 = 37,
1383 D3DPSREGISTER_UserVec2 = 38,
1384 D3DPSREGISTER_UserVec3 = 39,
1385 D3DPSREGISTER_UserVec4 = 40,
1386 D3DPSREGISTER_ViewTintColor = 41,
1387 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1388 D3DPSREGISTER_BloomColorSubtract = 43,
1389 D3DPSREGISTER_ViewToLight = 44, // float4x4
1390 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1391 D3DPSREGISTER_NormalmapScrollBlend = 52,
1392 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1397 /// information about each possible shader permutation
1398 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1399 /// currently selected permutation
1400 r_hlsl_permutation_t *r_hlsl_permutation;
1401 /// storage for permutations linked in the hash table
1402 memexpandablearray_t r_hlsl_permutationarray;
1404 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1406 //unsigned int hashdepth = 0;
1407 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1408 r_hlsl_permutation_t *p;
1409 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1411 if (p->mode == mode && p->permutation == permutation)
1413 //if (hashdepth > 10)
1414 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1419 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1421 p->permutation = permutation;
1422 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1423 r_hlsl_permutationhash[mode][hashindex] = p;
1424 //if (hashdepth > 10)
1425 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1429 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1432 if (!filename || !filename[0])
1434 if (!strcmp(filename, "hlsl/default.hlsl"))
1436 if (!hlslshaderstring)
1438 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439 if (hlslshaderstring)
1440 Con_DPrintf("Loading shaders from file %s...\n", filename);
1442 hlslshaderstring = (char *)builtinhlslshaderstring;
1444 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1445 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1446 return shaderstring;
1448 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1451 if (printfromdisknotice)
1452 Con_DPrintf("from disk %s... ", filename);
1453 return shaderstring;
1455 return shaderstring;
1459 //#include <d3dx9shader.h>
1460 //#include <d3dx9mesh.h>
1462 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1464 DWORD *vsbin = NULL;
1465 DWORD *psbin = NULL;
1466 fs_offset_t vsbinsize;
1467 fs_offset_t psbinsize;
1468 // IDirect3DVertexShader9 *vs = NULL;
1469 // IDirect3DPixelShader9 *ps = NULL;
1470 ID3DXBuffer *vslog = NULL;
1471 ID3DXBuffer *vsbuffer = NULL;
1472 ID3DXConstantTable *vsconstanttable = NULL;
1473 ID3DXBuffer *pslog = NULL;
1474 ID3DXBuffer *psbuffer = NULL;
1475 ID3DXConstantTable *psconstanttable = NULL;
1478 char temp[MAX_INPUTLINE];
1479 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1480 qboolean debugshader = gl_paranoid.integer != 0;
1481 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1482 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1485 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1486 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1488 if ((!vsbin && vertstring) || (!psbin && fragstring))
1490 const char* dllnames_d3dx9 [] =
1514 dllhandle_t d3dx9_dll = NULL;
1515 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1516 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1517 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1518 dllfunction_t d3dx9_dllfuncs[] =
1520 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1521 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1522 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1525 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1527 DWORD shaderflags = 0;
1529 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1530 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1531 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1532 if (vertstring && vertstring[0])
1536 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1537 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1538 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1539 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1542 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1545 vsbinsize = vsbuffer->GetBufferSize();
1546 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1547 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1548 vsbuffer->Release();
1552 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1553 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1557 if (fragstring && fragstring[0])
1561 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1562 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1563 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1564 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1567 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1570 psbinsize = psbuffer->GetBufferSize();
1571 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1572 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1573 psbuffer->Release();
1577 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1578 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1582 Sys_UnloadLibrary(&d3dx9_dll);
1585 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1589 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1590 if (FAILED(vsresult))
1591 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1592 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1593 if (FAILED(psresult))
1594 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1596 // free the shader data
1597 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1598 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1601 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1604 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1605 int vertstring_length = 0;
1606 int geomstring_length = 0;
1607 int fragstring_length = 0;
1609 char *vertexstring, *geometrystring, *fragmentstring;
1610 char *vertstring, *geomstring, *fragstring;
1611 char permutationname[256];
1612 char cachename[256];
1613 int vertstrings_count = 0;
1614 int geomstrings_count = 0;
1615 int fragstrings_count = 0;
1616 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1617 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1618 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1623 p->vertexshader = NULL;
1624 p->pixelshader = NULL;
1626 permutationname[0] = 0;
1628 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1629 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1630 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1632 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1633 strlcat(cachename, "hlsl/", sizeof(cachename));
1635 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1636 vertstrings_count = 0;
1637 geomstrings_count = 0;
1638 fragstrings_count = 0;
1639 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1640 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1641 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1643 // the first pretext is which type of shader to compile as
1644 // (later these will all be bound together as a program object)
1645 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1646 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1647 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1649 // the second pretext is the mode (for example a light source)
1650 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1651 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1652 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1653 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1654 strlcat(cachename, modeinfo->name, sizeof(cachename));
1656 // now add all the permutation pretexts
1657 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1659 if (permutation & (1<<i))
1661 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1662 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1663 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1664 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1665 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1669 // keep line numbers correct
1670 vertstrings_list[vertstrings_count++] = "\n";
1671 geomstrings_list[geomstrings_count++] = "\n";
1672 fragstrings_list[fragstrings_count++] = "\n";
1677 R_CompileShader_AddStaticParms(mode, permutation);
1678 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1679 vertstrings_count += shaderstaticparms_count;
1680 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1681 geomstrings_count += shaderstaticparms_count;
1682 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683 fragstrings_count += shaderstaticparms_count;
1685 // replace spaces in the cachename with _ characters
1686 for (i = 0;cachename[i];i++)
1687 if (cachename[i] == ' ')
1690 // now append the shader text itself
1691 vertstrings_list[vertstrings_count++] = vertexstring;
1692 geomstrings_list[geomstrings_count++] = geometrystring;
1693 fragstrings_list[fragstrings_count++] = fragmentstring;
1695 // if any sources were NULL, clear the respective list
1697 vertstrings_count = 0;
1698 if (!geometrystring)
1699 geomstrings_count = 0;
1700 if (!fragmentstring)
1701 fragstrings_count = 0;
1703 vertstring_length = 0;
1704 for (i = 0;i < vertstrings_count;i++)
1705 vertstring_length += strlen(vertstrings_list[i]);
1706 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1707 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1708 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1710 geomstring_length = 0;
1711 for (i = 0;i < geomstrings_count;i++)
1712 geomstring_length += strlen(geomstrings_list[i]);
1713 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1714 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1715 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1717 fragstring_length = 0;
1718 for (i = 0;i < fragstrings_count;i++)
1719 fragstring_length += strlen(fragstrings_list[i]);
1720 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1721 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1722 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1724 // try to load the cached shader, or generate one
1725 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1727 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1728 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1730 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1734 Mem_Free(vertstring);
1736 Mem_Free(geomstring);
1738 Mem_Free(fragstring);
1740 Mem_Free(vertexstring);
1742 Mem_Free(geometrystring);
1744 Mem_Free(fragmentstring);
1747 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1748 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1749 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);}
1750 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);}
1751 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);}
1752 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);}
1754 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1755 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1756 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);}
1757 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);}
1758 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);}
1759 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);}
1761 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1763 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1764 if (r_hlsl_permutation != perm)
1766 r_hlsl_permutation = perm;
1767 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1769 if (!r_hlsl_permutation->compiled)
1770 R_HLSL_CompilePermutation(perm, mode, permutation);
1771 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1773 // remove features until we find a valid permutation
1775 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1777 // reduce i more quickly whenever it would not remove any bits
1778 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1779 if (!(permutation & j))
1782 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1783 if (!r_hlsl_permutation->compiled)
1784 R_HLSL_CompilePermutation(perm, mode, permutation);
1785 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1788 if (i >= SHADERPERMUTATION_COUNT)
1790 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1791 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1792 return; // no bit left to clear, entire mode is broken
1796 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1797 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1799 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1800 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1801 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1805 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1807 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1808 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1809 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1810 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1813 void R_GLSL_Restart_f(void)
1815 unsigned int i, limit;
1816 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1817 Mem_Free(glslshaderstring);
1818 glslshaderstring = NULL;
1819 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1820 Mem_Free(hlslshaderstring);
1821 hlslshaderstring = NULL;
1822 switch(vid.renderpath)
1824 case RENDERPATH_D3D9:
1827 r_hlsl_permutation_t *p;
1828 r_hlsl_permutation = NULL;
1829 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1830 for (i = 0;i < limit;i++)
1832 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1834 if (p->vertexshader)
1835 IDirect3DVertexShader9_Release(p->vertexshader);
1837 IDirect3DPixelShader9_Release(p->pixelshader);
1838 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1841 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1845 case RENDERPATH_D3D10:
1846 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1848 case RENDERPATH_D3D11:
1849 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1851 case RENDERPATH_GL20:
1852 case RENDERPATH_GLES2:
1854 r_glsl_permutation_t *p;
1855 r_glsl_permutation = NULL;
1856 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1857 for (i = 0;i < limit;i++)
1859 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1861 GL_Backend_FreeProgram(p->program);
1862 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1865 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1868 case RENDERPATH_GL11:
1869 case RENDERPATH_GL13:
1870 case RENDERPATH_GLES1:
1872 case RENDERPATH_SOFT:
1877 void R_GLSL_DumpShader_f(void)
1882 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1885 FS_Print(file, "/* The engine may define the following macros:\n");
1886 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887 for (i = 0;i < SHADERMODE_COUNT;i++)
1888 FS_Print(file, glslshadermodeinfo[i].pretext);
1889 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890 FS_Print(file, shaderpermutationinfo[i].pretext);
1891 FS_Print(file, "*/\n");
1892 FS_Print(file, builtinshaderstring);
1894 Con_Printf("glsl/default.glsl written\n");
1897 Con_Printf("failed to write to glsl/default.glsl\n");
1899 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1902 FS_Print(file, "/* The engine may define the following macros:\n");
1903 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1904 for (i = 0;i < SHADERMODE_COUNT;i++)
1905 FS_Print(file, hlslshadermodeinfo[i].pretext);
1906 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1907 FS_Print(file, shaderpermutationinfo[i].pretext);
1908 FS_Print(file, "*/\n");
1909 FS_Print(file, builtinhlslshaderstring);
1911 Con_Printf("hlsl/default.hlsl written\n");
1914 Con_Printf("failed to write to hlsl/default.hlsl\n");
1917 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1919 unsigned int permutation = 0;
1920 if (r_trippy.integer && !notrippy)
1921 permutation |= SHADERPERMUTATION_TRIPPY;
1922 permutation |= SHADERPERMUTATION_VIEWTINT;
1924 permutation |= SHADERPERMUTATION_DIFFUSE;
1926 permutation |= SHADERPERMUTATION_SPECULAR;
1927 if (texturemode == GL_MODULATE)
1928 permutation |= SHADERPERMUTATION_COLORMAPPING;
1929 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1930 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1931 else if (texturemode == GL_ADD)
1932 permutation |= SHADERPERMUTATION_GLOW;
1933 else if (texturemode == GL_DECAL)
1934 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1936 texturemode = GL_MODULATE;
1937 if (vid.allowalphatocoverage)
1938 GL_AlphaToCoverage(false);
1939 switch (vid.renderpath)
1941 case RENDERPATH_D3D9:
1943 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1944 R_Mesh_TexBind(GL20TU_FIRST , first );
1945 R_Mesh_TexBind(GL20TU_SECOND, second);
1946 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1947 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1950 case RENDERPATH_D3D10:
1951 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953 case RENDERPATH_D3D11:
1954 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956 case RENDERPATH_GL20:
1957 case RENDERPATH_GLES2:
1958 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1959 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1960 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1961 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1962 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1964 case RENDERPATH_GL13:
1965 case RENDERPATH_GLES1:
1966 R_Mesh_TexBind(0, first );
1967 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1968 R_Mesh_TexBind(1, second);
1970 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1972 case RENDERPATH_GL11:
1973 R_Mesh_TexBind(0, first );
1975 case RENDERPATH_SOFT:
1976 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1977 R_Mesh_TexBind(GL20TU_FIRST , first );
1978 R_Mesh_TexBind(GL20TU_SECOND, second);
1983 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1985 unsigned int permutation = 0;
1986 if (r_trippy.integer && !notrippy)
1987 permutation |= SHADERPERMUTATION_TRIPPY;
1988 if (vid.allowalphatocoverage)
1989 GL_AlphaToCoverage(false);
1990 switch (vid.renderpath)
1992 case RENDERPATH_D3D9:
1994 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1997 case RENDERPATH_D3D10:
1998 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2000 case RENDERPATH_D3D11:
2001 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2003 case RENDERPATH_GL20:
2004 case RENDERPATH_GLES2:
2005 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2007 case RENDERPATH_GL13:
2008 case RENDERPATH_GLES1:
2009 R_Mesh_TexBind(0, 0);
2010 R_Mesh_TexBind(1, 0);
2012 case RENDERPATH_GL11:
2013 R_Mesh_TexBind(0, 0);
2015 case RENDERPATH_SOFT:
2016 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2021 void R_SetupShader_ShowDepth(qboolean notrippy)
2023 int permutation = 0;
2024 if (r_trippy.integer && !notrippy)
2025 permutation |= SHADERPERMUTATION_TRIPPY;
2026 if (vid.allowalphatocoverage)
2027 GL_AlphaToCoverage(false);
2028 switch (vid.renderpath)
2030 case RENDERPATH_D3D9:
2032 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2035 case RENDERPATH_D3D10:
2036 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2038 case RENDERPATH_D3D11:
2039 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2041 case RENDERPATH_GL20:
2042 case RENDERPATH_GLES2:
2043 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2045 case RENDERPATH_GL13:
2046 case RENDERPATH_GLES1:
2048 case RENDERPATH_GL11:
2050 case RENDERPATH_SOFT:
2051 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2056 extern qboolean r_shadow_usingdeferredprepass;
2057 extern cvar_t r_shadow_deferred_8bitrange;
2058 extern rtexture_t *r_shadow_attenuationgradienttexture;
2059 extern rtexture_t *r_shadow_attenuation2dtexture;
2060 extern rtexture_t *r_shadow_attenuation3dtexture;
2061 extern qboolean r_shadow_usingshadowmap2d;
2062 extern qboolean r_shadow_usingshadowmaportho;
2063 extern float r_shadow_shadowmap_texturescale[2];
2064 extern float r_shadow_shadowmap_parameters[4];
2065 extern qboolean r_shadow_shadowmapvsdct;
2066 extern qboolean r_shadow_shadowmapsampler;
2067 extern int r_shadow_shadowmappcf;
2068 extern rtexture_t *r_shadow_shadowmap2dtexture;
2069 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2070 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2071 extern matrix4x4_t r_shadow_shadowmapmatrix;
2072 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2073 extern int r_shadow_prepass_width;
2074 extern int r_shadow_prepass_height;
2075 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2076 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2077 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2078 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2079 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2081 #define BLENDFUNC_ALLOWS_COLORMOD 1
2082 #define BLENDFUNC_ALLOWS_FOG 2
2083 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2084 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2085 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2086 static int R_BlendFuncFlags(int src, int dst)
2090 // a blendfunc allows colormod if:
2091 // a) it can never keep the destination pixel invariant, or
2092 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2093 // this is to prevent unintended side effects from colormod
2095 // a blendfunc allows fog if:
2096 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2097 // this is to prevent unintended side effects from fog
2099 // these checks are the output of fogeval.pl
2101 r |= BLENDFUNC_ALLOWS_COLORMOD;
2102 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2103 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2104 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2105 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2106 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2111 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2112 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2113 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2114 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2115 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2117 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2118 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2119 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2120 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2121 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2122 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2127 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)
2129 // select a permutation of the lighting shader appropriate to this
2130 // combination of texture, entity, light source, and fogging, only use the
2131 // minimum features necessary to avoid wasting rendering time in the
2132 // fragment shader on features that are not being used
2133 unsigned int permutation = 0;
2134 unsigned int mode = 0;
2136 static float dummy_colormod[3] = {1, 1, 1};
2137 float *colormod = rsurface.colormod;
2139 matrix4x4_t tempmatrix;
2140 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2141 if (r_trippy.integer && !notrippy)
2142 permutation |= SHADERPERMUTATION_TRIPPY;
2143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2144 permutation |= SHADERPERMUTATION_ALPHAKILL;
2145 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2146 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2147 if (rsurfacepass == RSURFPASS_BACKGROUND)
2149 // distorted background
2150 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2152 mode = SHADERMODE_WATER;
2153 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2155 // this is the right thing to do for wateralpha
2156 GL_BlendFunc(GL_ONE, GL_ZERO);
2157 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2161 // this is the right thing to do for entity alpha
2162 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2163 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2166 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2168 mode = SHADERMODE_REFRACTION;
2169 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2170 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2174 mode = SHADERMODE_GENERIC;
2175 permutation |= SHADERPERMUTATION_DIFFUSE;
2176 GL_BlendFunc(GL_ONE, GL_ZERO);
2177 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2179 if (vid.allowalphatocoverage)
2180 GL_AlphaToCoverage(false);
2182 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2184 if (r_glsl_offsetmapping.integer)
2186 switch(rsurface.texture->offsetmapping)
2188 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2189 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2190 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2191 case OFFSETMAPPING_OFF: break;
2194 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2195 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2196 // normalmap (deferred prepass), may use alpha test on diffuse
2197 mode = SHADERMODE_DEFERREDGEOMETRY;
2198 GL_BlendFunc(GL_ONE, GL_ZERO);
2199 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2200 if (vid.allowalphatocoverage)
2201 GL_AlphaToCoverage(false);
2203 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2205 if (r_glsl_offsetmapping.integer)
2207 switch(rsurface.texture->offsetmapping)
2209 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2210 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2211 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2212 case OFFSETMAPPING_OFF: break;
2215 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2216 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2218 mode = SHADERMODE_LIGHTSOURCE;
2219 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2220 permutation |= SHADERPERMUTATION_CUBEFILTER;
2221 if (diffusescale > 0)
2222 permutation |= SHADERPERMUTATION_DIFFUSE;
2223 if (specularscale > 0)
2224 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2225 if (r_refdef.fogenabled)
2226 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2227 if (rsurface.texture->colormapping)
2228 permutation |= SHADERPERMUTATION_COLORMAPPING;
2229 if (r_shadow_usingshadowmap2d)
2231 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2232 if(r_shadow_shadowmapvsdct)
2233 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2235 if (r_shadow_shadowmapsampler)
2236 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2237 if (r_shadow_shadowmappcf > 1)
2238 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2239 else if (r_shadow_shadowmappcf)
2240 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2242 if (rsurface.texture->reflectmasktexture)
2243 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2244 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2245 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2246 if (vid.allowalphatocoverage)
2247 GL_AlphaToCoverage(false);
2249 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2251 if (r_glsl_offsetmapping.integer)
2253 switch(rsurface.texture->offsetmapping)
2255 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2256 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2258 case OFFSETMAPPING_OFF: break;
2261 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2262 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2263 // unshaded geometry (fullbright or ambient model lighting)
2264 mode = SHADERMODE_FLATCOLOR;
2265 ambientscale = diffusescale = specularscale = 0;
2266 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2267 permutation |= SHADERPERMUTATION_GLOW;
2268 if (r_refdef.fogenabled)
2269 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270 if (rsurface.texture->colormapping)
2271 permutation |= SHADERPERMUTATION_COLORMAPPING;
2272 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2274 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2277 if (r_shadow_shadowmapsampler)
2278 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2279 if (r_shadow_shadowmappcf > 1)
2280 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2281 else if (r_shadow_shadowmappcf)
2282 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2284 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2285 permutation |= SHADERPERMUTATION_REFLECTION;
2286 if (rsurface.texture->reflectmasktexture)
2287 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2288 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2289 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2290 // when using alphatocoverage, we don't need alphakill
2291 if (vid.allowalphatocoverage)
2293 if (r_transparent_alphatocoverage.integer)
2295 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2296 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2299 GL_AlphaToCoverage(false);
2302 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2304 if (r_glsl_offsetmapping.integer)
2306 switch(rsurface.texture->offsetmapping)
2308 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2309 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2310 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2311 case OFFSETMAPPING_OFF: break;
2314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2315 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2316 // directional model lighting
2317 mode = SHADERMODE_LIGHTDIRECTION;
2318 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2319 permutation |= SHADERPERMUTATION_GLOW;
2320 permutation |= SHADERPERMUTATION_DIFFUSE;
2321 if (specularscale > 0)
2322 permutation |= SHADERPERMUTATION_SPECULAR;
2323 if (r_refdef.fogenabled)
2324 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2325 if (rsurface.texture->colormapping)
2326 permutation |= SHADERPERMUTATION_COLORMAPPING;
2327 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2329 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2330 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2332 if (r_shadow_shadowmapsampler)
2333 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2334 if (r_shadow_shadowmappcf > 1)
2335 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2336 else if (r_shadow_shadowmappcf)
2337 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2339 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2340 permutation |= SHADERPERMUTATION_REFLECTION;
2341 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2342 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2343 if (rsurface.texture->reflectmasktexture)
2344 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2345 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2347 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2348 if (r_shadow_bouncegriddirectional)
2349 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2351 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353 // when using alphatocoverage, we don't need alphakill
2354 if (vid.allowalphatocoverage)
2356 if (r_transparent_alphatocoverage.integer)
2358 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2359 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2362 GL_AlphaToCoverage(false);
2365 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2367 if (r_glsl_offsetmapping.integer)
2369 switch(rsurface.texture->offsetmapping)
2371 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2372 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2373 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2374 case OFFSETMAPPING_OFF: break;
2377 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2378 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2379 // ambient model lighting
2380 mode = SHADERMODE_LIGHTDIRECTION;
2381 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2382 permutation |= SHADERPERMUTATION_GLOW;
2383 if (r_refdef.fogenabled)
2384 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2385 if (rsurface.texture->colormapping)
2386 permutation |= SHADERPERMUTATION_COLORMAPPING;
2387 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2389 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2390 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2392 if (r_shadow_shadowmapsampler)
2393 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2394 if (r_shadow_shadowmappcf > 1)
2395 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2396 else if (r_shadow_shadowmappcf)
2397 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2399 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2400 permutation |= SHADERPERMUTATION_REFLECTION;
2401 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2402 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2403 if (rsurface.texture->reflectmasktexture)
2404 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2405 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2407 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2408 if (r_shadow_bouncegriddirectional)
2409 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2411 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2412 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413 // when using alphatocoverage, we don't need alphakill
2414 if (vid.allowalphatocoverage)
2416 if (r_transparent_alphatocoverage.integer)
2418 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2419 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2422 GL_AlphaToCoverage(false);
2427 if (r_glsl_offsetmapping.integer)
2429 switch(rsurface.texture->offsetmapping)
2431 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2432 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2433 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2434 case OFFSETMAPPING_OFF: break;
2437 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2438 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2440 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2441 permutation |= SHADERPERMUTATION_GLOW;
2442 if (r_refdef.fogenabled)
2443 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2444 if (rsurface.texture->colormapping)
2445 permutation |= SHADERPERMUTATION_COLORMAPPING;
2446 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2448 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2449 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2451 if (r_shadow_shadowmapsampler)
2452 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2453 if (r_shadow_shadowmappcf > 1)
2454 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2455 else if (r_shadow_shadowmappcf)
2456 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2458 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2459 permutation |= SHADERPERMUTATION_REFLECTION;
2460 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2461 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2462 if (rsurface.texture->reflectmasktexture)
2463 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2464 if (FAKELIGHT_ENABLED)
2466 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2467 mode = SHADERMODE_FAKELIGHT;
2468 permutation |= SHADERPERMUTATION_DIFFUSE;
2469 if (specularscale > 0)
2470 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2472 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2474 // deluxemapping (light direction texture)
2475 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2476 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2478 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2479 permutation |= SHADERPERMUTATION_DIFFUSE;
2480 if (specularscale > 0)
2481 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2483 else if (r_glsl_deluxemapping.integer >= 2)
2485 // fake deluxemapping (uniform light direction in tangentspace)
2486 if (rsurface.uselightmaptexture)
2487 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2489 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2490 permutation |= SHADERPERMUTATION_DIFFUSE;
2491 if (specularscale > 0)
2492 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2494 else if (rsurface.uselightmaptexture)
2496 // ordinary lightmapping (q1bsp, q3bsp)
2497 mode = SHADERMODE_LIGHTMAP;
2501 // ordinary vertex coloring (q3bsp)
2502 mode = SHADERMODE_VERTEXCOLOR;
2504 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2506 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2507 if (r_shadow_bouncegriddirectional)
2508 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2510 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2511 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2512 // when using alphatocoverage, we don't need alphakill
2513 if (vid.allowalphatocoverage)
2515 if (r_transparent_alphatocoverage.integer)
2517 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2518 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2521 GL_AlphaToCoverage(false);
2524 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2525 colormod = dummy_colormod;
2526 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2527 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2528 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2529 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2530 switch(vid.renderpath)
2532 case RENDERPATH_D3D9:
2534 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);
2535 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2536 R_SetupShader_SetPermutationHLSL(mode, permutation);
2537 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2538 if (mode == SHADERMODE_LIGHTSOURCE)
2540 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2541 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2545 if (mode == SHADERMODE_LIGHTDIRECTION)
2547 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2550 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2551 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2552 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2553 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2554 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2556 if (mode == SHADERMODE_LIGHTSOURCE)
2558 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2559 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2560 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2561 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2562 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2564 // additive passes are only darkened by fog, not tinted
2565 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2566 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2570 if (mode == SHADERMODE_FLATCOLOR)
2572 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2574 else if (mode == SHADERMODE_LIGHTDIRECTION)
2576 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]);
2577 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2578 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);
2579 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);
2580 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2581 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2582 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2586 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2587 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2588 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);
2589 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);
2590 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2592 // additive passes are only darkened by fog, not tinted
2593 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2594 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2596 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2597 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);
2598 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2599 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2600 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2601 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2602 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2603 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2604 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2605 if (mode == SHADERMODE_WATER)
2606 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2608 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2609 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2610 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2611 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));
2612 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2613 if (rsurface.texture->pantstexture)
2614 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2616 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2617 if (rsurface.texture->shirttexture)
2618 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2620 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2621 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2622 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2623 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2624 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2625 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2626 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2627 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2628 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2629 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2631 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer)
2632 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2633 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2635 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2636 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2637 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2638 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2639 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2640 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2641 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2642 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2643 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2644 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2645 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2646 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2647 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2648 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2649 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2650 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2651 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2652 if (rsurfacepass == RSURFPASS_BACKGROUND)
2654 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2655 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2656 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2660 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2662 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2663 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2664 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2665 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2666 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2668 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2669 if (rsurface.rtlight)
2671 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2672 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2677 case RENDERPATH_D3D10:
2678 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2680 case RENDERPATH_D3D11:
2681 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2683 case RENDERPATH_GL20:
2684 case RENDERPATH_GLES2:
2685 if (!vid.useinterleavedarrays)
2687 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);
2688 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2689 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2690 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2691 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2692 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2693 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2694 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2698 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);
2699 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2701 R_SetupShader_SetPermutationGLSL(mode, permutation);
2702 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2703 if (mode == SHADERMODE_LIGHTSOURCE)
2705 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2706 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2707 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2708 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2709 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2710 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);
2712 // additive passes are only darkened by fog, not tinted
2713 if (r_glsl_permutation->loc_FogColor >= 0)
2714 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2715 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2719 if (mode == SHADERMODE_FLATCOLOR)
2721 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2723 else if (mode == SHADERMODE_LIGHTDIRECTION)
2725 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]);
2726 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]);
2727 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);
2728 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);
2729 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);
2730 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]);
2731 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]);
2735 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]);
2736 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]);
2737 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);
2738 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);
2739 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);
2741 // additive passes are only darkened by fog, not tinted
2742 if (r_glsl_permutation->loc_FogColor >= 0)
2744 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2745 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2747 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2749 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);
2750 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]);
2751 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]);
2752 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]);
2753 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]);
2754 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2755 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2756 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2757 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]);
2759 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2760 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2761 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2762 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]);
2763 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]);
2765 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2766 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));
2767 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2768 if (r_glsl_permutation->loc_Color_Pants >= 0)
2770 if (rsurface.texture->pantstexture)
2771 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2773 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2775 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2777 if (rsurface.texture->shirttexture)
2778 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2780 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2782 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]);
2783 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2784 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2785 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2786 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2787 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2788 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2789 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2790 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2792 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2793 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]);
2794 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2795 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);}
2796 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2798 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2799 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2800 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2801 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2802 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2803 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2804 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2805 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2806 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2807 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2808 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2809 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2810 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2811 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2812 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);
2813 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2814 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2815 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2816 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2817 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2818 if (rsurfacepass == RSURFPASS_BACKGROUND)
2820 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);
2821 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);
2822 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);
2826 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);
2828 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2829 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2830 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2831 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2832 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2834 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2835 if (rsurface.rtlight)
2837 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2838 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2841 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2844 case RENDERPATH_GL11:
2845 case RENDERPATH_GL13:
2846 case RENDERPATH_GLES1:
2848 case RENDERPATH_SOFT:
2849 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);
2850 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2851 R_SetupShader_SetPermutationSoft(mode, permutation);
2852 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2853 if (mode == SHADERMODE_LIGHTSOURCE)
2855 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2856 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2857 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2858 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2859 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2860 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2862 // additive passes are only darkened by fog, not tinted
2863 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2868 if (mode == SHADERMODE_FLATCOLOR)
2870 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2872 else if (mode == SHADERMODE_LIGHTDIRECTION)
2874 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]);
2875 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2876 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);
2877 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);
2878 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2879 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]);
2880 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2885 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2886 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);
2887 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);
2888 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2890 // additive passes are only darkened by fog, not tinted
2891 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2894 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2895 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);
2896 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2897 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2898 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]);
2899 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]);
2900 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2901 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2902 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2903 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2905 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2906 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2907 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2908 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2909 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]);
2911 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2912 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));
2913 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2914 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2916 if (rsurface.texture->pantstexture)
2917 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2919 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2921 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2923 if (rsurface.texture->shirttexture)
2924 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2926 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2928 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2929 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2930 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2931 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2932 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2933 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2934 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2935 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2938 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2939 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2941 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2942 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2943 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2944 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2945 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2946 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2947 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2948 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2949 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2950 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2951 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2952 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2953 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2954 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2955 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2956 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2957 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2958 if (rsurfacepass == RSURFPASS_BACKGROUND)
2960 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2961 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2962 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2966 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2968 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2969 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2970 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2971 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2972 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2974 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2975 if (rsurface.rtlight)
2977 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2978 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2985 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2987 // select a permutation of the lighting shader appropriate to this
2988 // combination of texture, entity, light source, and fogging, only use the
2989 // minimum features necessary to avoid wasting rendering time in the
2990 // fragment shader on features that are not being used
2991 unsigned int permutation = 0;
2992 unsigned int mode = 0;
2993 const float *lightcolorbase = rtlight->currentcolor;
2994 float ambientscale = rtlight->ambientscale;
2995 float diffusescale = rtlight->diffusescale;
2996 float specularscale = rtlight->specularscale;
2997 // this is the location of the light in view space
2998 vec3_t viewlightorigin;
2999 // this transforms from view space (camera) to light space (cubemap)
3000 matrix4x4_t viewtolight;
3001 matrix4x4_t lighttoview;
3002 float viewtolight16f[16];
3003 float range = 1.0f / r_shadow_deferred_8bitrange.value;
3005 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3006 if (rtlight->currentcubemap != r_texture_whitecube)
3007 permutation |= SHADERPERMUTATION_CUBEFILTER;
3008 if (diffusescale > 0)
3009 permutation |= SHADERPERMUTATION_DIFFUSE;
3010 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3011 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3012 if (r_shadow_usingshadowmap2d)
3014 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3015 if (r_shadow_shadowmapvsdct)
3016 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3018 if (r_shadow_shadowmapsampler)
3019 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3020 if (r_shadow_shadowmappcf > 1)
3021 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3022 else if (r_shadow_shadowmappcf)
3023 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3025 if (vid.allowalphatocoverage)
3026 GL_AlphaToCoverage(false);
3027 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3028 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3029 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3030 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3031 switch(vid.renderpath)
3033 case RENDERPATH_D3D9:
3035 R_SetupShader_SetPermutationHLSL(mode, permutation);
3036 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3037 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3038 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3039 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3040 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3041 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3042 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3043 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3044 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3045 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3047 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3048 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3049 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3050 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3051 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3052 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3055 case RENDERPATH_D3D10:
3056 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3058 case RENDERPATH_D3D11:
3059 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3061 case RENDERPATH_GL20:
3062 case RENDERPATH_GLES2:
3063 R_SetupShader_SetPermutationGLSL(mode, permutation);
3064 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3065 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3066 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);
3067 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);
3068 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);
3069 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]);
3070 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]);
3071 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));
3072 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]);
3073 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3075 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3076 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3077 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3078 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3079 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3080 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3082 case RENDERPATH_GL11:
3083 case RENDERPATH_GL13:
3084 case RENDERPATH_GLES1:
3086 case RENDERPATH_SOFT:
3087 R_SetupShader_SetPermutationGLSL(mode, permutation);
3088 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3089 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3090 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3091 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3092 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3093 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3094 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]);
3095 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));
3096 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3097 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3099 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3100 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3101 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3102 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3103 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3104 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3109 #define SKINFRAME_HASH 1024
3113 int loadsequence; // incremented each level change
3114 memexpandablearray_t array;
3115 skinframe_t *hash[SKINFRAME_HASH];
3118 r_skinframe_t r_skinframe;
3120 void R_SkinFrame_PrepareForPurge(void)
3122 r_skinframe.loadsequence++;
3123 // wrap it without hitting zero
3124 if (r_skinframe.loadsequence >= 200)
3125 r_skinframe.loadsequence = 1;
3128 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3132 // mark the skinframe as used for the purging code
3133 skinframe->loadsequence = r_skinframe.loadsequence;
3136 void R_SkinFrame_Purge(void)
3140 for (i = 0;i < SKINFRAME_HASH;i++)
3142 for (s = r_skinframe.hash[i];s;s = s->next)
3144 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3146 if (s->merged == s->base)
3148 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3149 R_PurgeTexture(s->stain );s->stain = NULL;
3150 R_PurgeTexture(s->merged);s->merged = NULL;
3151 R_PurgeTexture(s->base );s->base = NULL;
3152 R_PurgeTexture(s->pants );s->pants = NULL;
3153 R_PurgeTexture(s->shirt );s->shirt = NULL;
3154 R_PurgeTexture(s->nmap );s->nmap = NULL;
3155 R_PurgeTexture(s->gloss );s->gloss = NULL;
3156 R_PurgeTexture(s->glow );s->glow = NULL;
3157 R_PurgeTexture(s->fog );s->fog = NULL;
3158 R_PurgeTexture(s->reflect);s->reflect = NULL;
3159 s->loadsequence = 0;
3165 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3167 char basename[MAX_QPATH];
3169 Image_StripImageExtension(name, basename, sizeof(basename));
3171 if( last == NULL ) {
3173 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3174 item = r_skinframe.hash[hashindex];
3179 // linearly search through the hash bucket
3180 for( ; item ; item = item->next ) {
3181 if( !strcmp( item->basename, basename ) ) {
3188 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3192 char basename[MAX_QPATH];
3194 Image_StripImageExtension(name, basename, sizeof(basename));
3196 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3197 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3198 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3202 rtexture_t *dyntexture;
3203 // check whether its a dynamic texture
3204 dyntexture = CL_GetDynTexture( basename );
3205 if (!add && !dyntexture)
3207 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3208 memset(item, 0, sizeof(*item));
3209 strlcpy(item->basename, basename, sizeof(item->basename));
3210 item->base = dyntexture; // either NULL or dyntexture handle
3211 item->textureflags = textureflags;
3212 item->comparewidth = comparewidth;
3213 item->compareheight = compareheight;
3214 item->comparecrc = comparecrc;
3215 item->next = r_skinframe.hash[hashindex];
3216 r_skinframe.hash[hashindex] = item;
3218 else if( item->base == NULL )
3220 rtexture_t *dyntexture;
3221 // check whether its a dynamic texture
3222 // 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]
3223 dyntexture = CL_GetDynTexture( basename );
3224 item->base = dyntexture; // either NULL or dyntexture handle
3227 R_SkinFrame_MarkUsed(item);
3231 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3233 unsigned long long avgcolor[5], wsum; \
3241 for(pix = 0; pix < cnt; ++pix) \
3244 for(comp = 0; comp < 3; ++comp) \
3246 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3249 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3251 for(comp = 0; comp < 3; ++comp) \
3252 avgcolor[comp] += getpixel * w; \
3255 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3256 avgcolor[4] += getpixel; \
3258 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3260 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3261 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3262 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3263 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3266 extern cvar_t gl_picmip;
3267 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3270 unsigned char *pixels;
3271 unsigned char *bumppixels;
3272 unsigned char *basepixels = NULL;
3273 int basepixels_width = 0;
3274 int basepixels_height = 0;
3275 skinframe_t *skinframe;
3276 rtexture_t *ddsbase = NULL;
3277 qboolean ddshasalpha = false;
3278 float ddsavgcolor[4];
3279 char basename[MAX_QPATH];
3280 int miplevel = R_PicmipForFlags(textureflags);
3281 int savemiplevel = miplevel;
3284 if (cls.state == ca_dedicated)
3287 // return an existing skinframe if already loaded
3288 // if loading of the first image fails, don't make a new skinframe as it
3289 // would cause all future lookups of this to be missing
3290 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3291 if (skinframe && skinframe->base)
3294 Image_StripImageExtension(name, basename, sizeof(basename));
3296 // check for DDS texture file first
3297 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3299 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3300 if (basepixels == NULL)
3304 // FIXME handle miplevel
3306 if (developer_loading.integer)
3307 Con_Printf("loading skin \"%s\"\n", name);
3309 // we've got some pixels to store, so really allocate this new texture now
3311 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3312 skinframe->stain = NULL;
3313 skinframe->merged = NULL;
3314 skinframe->base = NULL;
3315 skinframe->pants = NULL;
3316 skinframe->shirt = NULL;
3317 skinframe->nmap = NULL;
3318 skinframe->gloss = NULL;
3319 skinframe->glow = NULL;
3320 skinframe->fog = NULL;
3321 skinframe->reflect = NULL;
3322 skinframe->hasalpha = false;
3326 skinframe->base = ddsbase;
3327 skinframe->hasalpha = ddshasalpha;
3328 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3329 if (r_loadfog && skinframe->hasalpha)
3330 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3331 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3335 basepixels_width = image_width;
3336 basepixels_height = image_height;
3337 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);
3338 if (textureflags & TEXF_ALPHA)
3340 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3342 if (basepixels[j] < 255)
3344 skinframe->hasalpha = true;
3348 if (r_loadfog && skinframe->hasalpha)
3350 // has transparent pixels
3351 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3352 for (j = 0;j < image_width * image_height * 4;j += 4)
3357 pixels[j+3] = basepixels[j+3];
3359 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);
3363 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3365 //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]);
3366 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3367 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3368 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3369 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3375 mymiplevel = savemiplevel;
3376 if (r_loadnormalmap)
3377 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);
3378 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3380 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3381 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3382 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3383 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3386 // _norm is the name used by tenebrae and has been adopted as standard
3387 if (r_loadnormalmap && skinframe->nmap == NULL)
3389 mymiplevel = savemiplevel;
3390 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3392 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);
3396 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3398 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3399 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3400 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);
3402 Mem_Free(bumppixels);
3404 else if (r_shadow_bumpscale_basetexture.value > 0)
3406 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3407 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3408 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);
3412 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3413 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3417 // _luma is supported only for tenebrae compatibility
3418 // _glow is the preferred name
3419 mymiplevel = savemiplevel;
3420 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))))
3422 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);
3424 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3425 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3427 Mem_Free(pixels);pixels = NULL;
3430 mymiplevel = savemiplevel;
3431 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3433 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3435 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3436 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3442 mymiplevel = savemiplevel;
3443 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3445 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);
3447 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3448 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3454 mymiplevel = savemiplevel;
3455 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3457 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);
3459 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3460 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3466 mymiplevel = savemiplevel;
3467 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3469 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);
3471 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3472 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3479 Mem_Free(basepixels);
3484 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3485 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3488 unsigned char *temp1, *temp2;
3489 skinframe_t *skinframe;
3491 if (cls.state == ca_dedicated)
3494 // if already loaded just return it, otherwise make a new skinframe
3495 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3496 if (skinframe && skinframe->base)
3499 skinframe->stain = NULL;
3500 skinframe->merged = NULL;
3501 skinframe->base = NULL;
3502 skinframe->pants = NULL;
3503 skinframe->shirt = NULL;
3504 skinframe->nmap = NULL;
3505 skinframe->gloss = NULL;
3506 skinframe->glow = NULL;
3507 skinframe->fog = NULL;
3508 skinframe->reflect = NULL;
3509 skinframe->hasalpha = false;
3511 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3515 if (developer_loading.integer)
3516 Con_Printf("loading 32bit skin \"%s\"\n", name);
3518 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3520 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3521 temp2 = temp1 + width * height * 4;
3522 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3523 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);
3526 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3527 if (textureflags & TEXF_ALPHA)
3529 for (i = 3;i < width * height * 4;i += 4)
3531 if (skindata[i] < 255)
3533 skinframe->hasalpha = true;
3537 if (r_loadfog && skinframe->hasalpha)
3539 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3540 memcpy(fogpixels, skindata, width * height * 4);
3541 for (i = 0;i < width * height * 4;i += 4)
3542 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3543 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3544 Mem_Free(fogpixels);
3548 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3549 //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]);
3554 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3558 skinframe_t *skinframe;
3560 if (cls.state == ca_dedicated)
3563 // if already loaded just return it, otherwise make a new skinframe
3564 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3565 if (skinframe && skinframe->base)
3568 skinframe->stain = NULL;
3569 skinframe->merged = NULL;
3570 skinframe->base = NULL;
3571 skinframe->pants = NULL;
3572 skinframe->shirt = NULL;
3573 skinframe->nmap = NULL;
3574 skinframe->gloss = NULL;
3575 skinframe->glow = NULL;
3576 skinframe->fog = NULL;
3577 skinframe->reflect = NULL;
3578 skinframe->hasalpha = false;
3580 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3584 if (developer_loading.integer)
3585 Con_Printf("loading quake skin \"%s\"\n", name);
3587 // 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)
3588 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3589 memcpy(skinframe->qpixels, skindata, width*height);
3590 skinframe->qwidth = width;
3591 skinframe->qheight = height;
3594 for (i = 0;i < width * height;i++)
3595 featuresmask |= palette_featureflags[skindata[i]];
3597 skinframe->hasalpha = false;
3598 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3599 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3600 skinframe->qgeneratemerged = true;
3601 skinframe->qgeneratebase = skinframe->qhascolormapping;
3602 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3604 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3605 //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]);
3610 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3614 unsigned char *skindata;
3616 if (!skinframe->qpixels)
3619 if (!skinframe->qhascolormapping)
3620 colormapped = false;
3624 if (!skinframe->qgeneratebase)
3629 if (!skinframe->qgeneratemerged)
3633 width = skinframe->qwidth;
3634 height = skinframe->qheight;
3635 skindata = skinframe->qpixels;
3637 if (skinframe->qgeneratenmap)
3639 unsigned char *temp1, *temp2;
3640 skinframe->qgeneratenmap = false;
3641 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3642 temp2 = temp1 + width * height * 4;
3643 // use either a custom palette or the quake palette
3644 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3645 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3646 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);
3650 if (skinframe->qgenerateglow)
3652 skinframe->qgenerateglow = false;
3653 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
3658 skinframe->qgeneratebase = false;
3659 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);
3660 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);
3661 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);
3665 skinframe->qgeneratemerged = false;
3666 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);
3669 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3671 Mem_Free(skinframe->qpixels);
3672 skinframe->qpixels = NULL;
3676 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)
3679 skinframe_t *skinframe;
3681 if (cls.state == ca_dedicated)
3684 // if already loaded just return it, otherwise make a new skinframe
3685 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3686 if (skinframe && skinframe->base)
3689 skinframe->stain = NULL;
3690 skinframe->merged = NULL;
3691 skinframe->base = NULL;
3692 skinframe->pants = NULL;
3693 skinframe->shirt = NULL;
3694 skinframe->nmap = NULL;
3695 skinframe->gloss = NULL;
3696 skinframe->glow = NULL;
3697 skinframe->fog = NULL;
3698 skinframe->reflect = NULL;
3699 skinframe->hasalpha = false;
3701 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3705 if (developer_loading.integer)
3706 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3708 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3709 if (textureflags & TEXF_ALPHA)
3711 for (i = 0;i < width * height;i++)
3713 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3715 skinframe->hasalpha = true;
3719 if (r_loadfog && skinframe->hasalpha)
3720 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3723 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3724 //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]);
3729 skinframe_t *R_SkinFrame_LoadMissing(void)
3731 skinframe_t *skinframe;
3733 if (cls.state == ca_dedicated)
3736 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3737 skinframe->stain = NULL;
3738 skinframe->merged = NULL;
3739 skinframe->base = NULL;
3740 skinframe->pants = NULL;
3741 skinframe->shirt = NULL;
3742 skinframe->nmap = NULL;
3743 skinframe->gloss = NULL;
3744 skinframe->glow = NULL;
3745 skinframe->fog = NULL;
3746 skinframe->reflect = NULL;
3747 skinframe->hasalpha = false;
3749 skinframe->avgcolor[0] = rand() / RAND_MAX;
3750 skinframe->avgcolor[1] = rand() / RAND_MAX;
3751 skinframe->avgcolor[2] = rand() / RAND_MAX;
3752 skinframe->avgcolor[3] = 1;
3757 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3758 typedef struct suffixinfo_s
3761 qboolean flipx, flipy, flipdiagonal;
3764 static suffixinfo_t suffix[3][6] =
3767 {"px", false, false, false},
3768 {"nx", false, false, false},
3769 {"py", false, false, false},
3770 {"ny", false, false, false},
3771 {"pz", false, false, false},
3772 {"nz", false, false, false}
3775 {"posx", false, false, false},
3776 {"negx", false, false, false},
3777 {"posy", false, false, false},
3778 {"negy", false, false, false},
3779 {"posz", false, false, false},
3780 {"negz", false, false, false}
3783 {"rt", true, false, true},
3784 {"lf", false, true, true},
3785 {"ft", true, true, false},
3786 {"bk", false, false, false},
3787 {"up", true, false, true},
3788 {"dn", true, false, true}
3792 static int componentorder[4] = {0, 1, 2, 3};
3794 rtexture_t *R_LoadCubemap(const char *basename)
3796 int i, j, cubemapsize;
3797 unsigned char *cubemappixels, *image_buffer;
3798 rtexture_t *cubemaptexture;
3800 // must start 0 so the first loadimagepixels has no requested width/height
3802 cubemappixels = NULL;
3803 cubemaptexture = NULL;
3804 // keep trying different suffix groups (posx, px, rt) until one loads
3805 for (j = 0;j < 3 && !cubemappixels;j++)
3807 // load the 6 images in the suffix group
3808 for (i = 0;i < 6;i++)
3810 // generate an image name based on the base and and suffix
3811 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3813 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3815 // an image loaded, make sure width and height are equal
3816 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3818 // if this is the first image to load successfully, allocate the cubemap memory
3819 if (!cubemappixels && image_width >= 1)
3821 cubemapsize = image_width;
3822 // note this clears to black, so unavailable sides are black
3823 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3825 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3827 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);
3830 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3832 Mem_Free(image_buffer);
3836 // if a cubemap loaded, upload it
3839 if (developer_loading.integer)
3840 Con_Printf("loading cubemap \"%s\"\n", basename);
3842 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);
3843 Mem_Free(cubemappixels);
3847 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3848 if (developer_loading.integer)
3850 Con_Printf("(tried tried images ");
3851 for (j = 0;j < 3;j++)
3852 for (i = 0;i < 6;i++)
3853 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3854 Con_Print(" and was unable to find any of them).\n");
3857 return cubemaptexture;
3860 rtexture_t *R_GetCubemap(const char *basename)
3863 for (i = 0;i < r_texture_numcubemaps;i++)
3864 if (r_texture_cubemaps[i] != NULL)
3865 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3866 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3867 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3868 return r_texture_whitecube;
3869 r_texture_numcubemaps++;
3870 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3871 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3872 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3873 return r_texture_cubemaps[i]->texture;
3876 void R_FreeCubemap(const char *basename)
3880 for (i = 0;i < r_texture_numcubemaps;i++)
3882 if (r_texture_cubemaps[i] != NULL)
3884 if (r_texture_cubemaps[i]->texture)
3886 if (developer_loading.integer)
3887 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3888 R_FreeTexture(r_texture_cubemaps[i]->texture);
3889 Mem_Free(r_texture_cubemaps[i]);
3890 r_texture_cubemaps[i] = NULL;
3896 void R_FreeCubemaps(void)
3899 for (i = 0;i < r_texture_numcubemaps;i++)
3901 if (developer_loading.integer)
3902 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3903 if (r_texture_cubemaps[i] != NULL)
3905 if (r_texture_cubemaps[i]->texture)
3906 R_FreeTexture(r_texture_cubemaps[i]->texture);
3907 Mem_Free(r_texture_cubemaps[i]);
3910 r_texture_numcubemaps = 0;
3913 void R_Main_FreeViewCache(void)
3915 if (r_refdef.viewcache.entityvisible)
3916 Mem_Free(r_refdef.viewcache.entityvisible);
3917 if (r_refdef.viewcache.world_pvsbits)
3918 Mem_Free(r_refdef.viewcache.world_pvsbits);
3919 if (r_refdef.viewcache.world_leafvisible)
3920 Mem_Free(r_refdef.viewcache.world_leafvisible);
3921 if (r_refdef.viewcache.world_surfacevisible)
3922 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3923 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3926 void R_Main_ResizeViewCache(void)
3928 int numentities = r_refdef.scene.numentities;
3929 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3930 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3931 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3932 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3933 if (r_refdef.viewcache.maxentities < numentities)
3935 r_refdef.viewcache.maxentities = numentities;
3936 if (r_refdef.viewcache.entityvisible)
3937 Mem_Free(r_refdef.viewcache.entityvisible);
3938 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3940 if (r_refdef.viewcache.world_numclusters != numclusters)
3942 r_refdef.viewcache.world_numclusters = numclusters;
3943 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3944 if (r_refdef.viewcache.world_pvsbits)
3945 Mem_Free(r_refdef.viewcache.world_pvsbits);
3946 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3948 if (r_refdef.viewcache.world_numleafs != numleafs)
3950 r_refdef.viewcache.world_numleafs = numleafs;
3951 if (r_refdef.viewcache.world_leafvisible)
3952 Mem_Free(r_refdef.viewcache.world_leafvisible);
3953 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3955 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3957 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3958 if (r_refdef.viewcache.world_surfacevisible)
3959 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3960 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3964 extern rtexture_t *loadingscreentexture;
3965 void gl_main_start(void)
3967 loadingscreentexture = NULL;
3968 r_texture_blanknormalmap = NULL;
3969 r_texture_white = NULL;
3970 r_texture_grey128 = NULL;
3971 r_texture_black = NULL;
3972 r_texture_whitecube = NULL;
3973 r_texture_normalizationcube = NULL;
3974 r_texture_fogattenuation = NULL;
3975 r_texture_fogheighttexture = NULL;
3976 r_texture_gammaramps = NULL;
3977 r_texture_numcubemaps = 0;
3979 r_loaddds = r_texture_dds_load.integer != 0;
3980 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3982 switch(vid.renderpath)
3984 case RENDERPATH_GL20:
3985 case RENDERPATH_D3D9:
3986 case RENDERPATH_D3D10:
3987 case RENDERPATH_D3D11:
3988 case RENDERPATH_SOFT:
3989 case RENDERPATH_GLES2:
3990 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3991 Cvar_SetValueQuick(&gl_combine, 1);
3992 Cvar_SetValueQuick(&r_glsl, 1);
3993 r_loadnormalmap = true;
3997 case RENDERPATH_GL13:
3998 case RENDERPATH_GLES1:
3999 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4000 Cvar_SetValueQuick(&gl_combine, 1);
4001 Cvar_SetValueQuick(&r_glsl, 0);
4002 r_loadnormalmap = false;
4003 r_loadgloss = false;
4006 case RENDERPATH_GL11:
4007 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4008 Cvar_SetValueQuick(&gl_combine, 0);
4009 Cvar_SetValueQuick(&r_glsl, 0);
4010 r_loadnormalmap = false;
4011 r_loadgloss = false;
4017 R_FrameData_Reset();
4021 memset(r_queries, 0, sizeof(r_queries));
4023 r_qwskincache = NULL;
4024 r_qwskincache_size = 0;
4026 // due to caching of texture_t references, the collision cache must be reset
4027 Collision_Cache_Reset(true);
4029 // set up r_skinframe loading system for textures
4030 memset(&r_skinframe, 0, sizeof(r_skinframe));
4031 r_skinframe.loadsequence = 1;
4032 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4034 r_main_texturepool = R_AllocTexturePool();
4035 R_BuildBlankTextures();
4037 if (vid.support.arb_texture_cube_map)
4040 R_BuildNormalizationCube();
4042 r_texture_fogattenuation = NULL;
4043 r_texture_fogheighttexture = NULL;
4044 r_texture_gammaramps = NULL;
4045 //r_texture_fogintensity = NULL;
4046 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4047 memset(&r_waterstate, 0, sizeof(r_waterstate));
4048 r_glsl_permutation = NULL;
4049 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4050 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4051 glslshaderstring = NULL;
4053 r_hlsl_permutation = NULL;
4054 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4055 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4057 hlslshaderstring = NULL;
4058 memset(&r_svbsp, 0, sizeof (r_svbsp));
4060 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4061 r_texture_numcubemaps = 0;
4063 r_refdef.fogmasktable_density = 0;
4066 void gl_main_shutdown(void)
4069 R_FrameData_Reset();
4071 R_Main_FreeViewCache();
4073 switch(vid.renderpath)
4075 case RENDERPATH_GL11:
4076 case RENDERPATH_GL13:
4077 case RENDERPATH_GL20:
4078 case RENDERPATH_GLES1:
4079 case RENDERPATH_GLES2:
4080 #ifdef GL_SAMPLES_PASSED_ARB
4082 qglDeleteQueriesARB(r_maxqueries, r_queries);
4085 case RENDERPATH_D3D9:
4086 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4088 case RENDERPATH_D3D10:
4089 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4091 case RENDERPATH_D3D11:
4092 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4094 case RENDERPATH_SOFT:
4100 memset(r_queries, 0, sizeof(r_queries));
4102 r_qwskincache = NULL;
4103 r_qwskincache_size = 0;
4105 // clear out the r_skinframe state
4106 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4107 memset(&r_skinframe, 0, sizeof(r_skinframe));
4110 Mem_Free(r_svbsp.nodes);
4111 memset(&r_svbsp, 0, sizeof (r_svbsp));
4112 R_FreeTexturePool(&r_main_texturepool);
4113 loadingscreentexture = NULL;
4114 r_texture_blanknormalmap = NULL;
4115 r_texture_white = NULL;
4116 r_texture_grey128 = NULL;
4117 r_texture_black = NULL;
4118 r_texture_whitecube = NULL;
4119 r_texture_normalizationcube = NULL;
4120 r_texture_fogattenuation = NULL;
4121 r_texture_fogheighttexture = NULL;
4122 r_texture_gammaramps = NULL;
4123 r_texture_numcubemaps = 0;
4124 //r_texture_fogintensity = NULL;
4125 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4126 memset(&r_waterstate, 0, sizeof(r_waterstate));
4129 r_glsl_permutation = NULL;
4130 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4131 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4132 glslshaderstring = NULL;
4134 r_hlsl_permutation = NULL;
4135 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4136 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4138 hlslshaderstring = NULL;
4141 extern void CL_ParseEntityLump(char *entitystring);
4142 void gl_main_newmap(void)
4144 // FIXME: move this code to client
4145 char *entities, entname[MAX_QPATH];
4147 Mem_Free(r_qwskincache);
4148 r_qwskincache = NULL;
4149 r_qwskincache_size = 0;
4152 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4153 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4155 CL_ParseEntityLump(entities);
4159 if (cl.worldmodel->brush.entities)
4160 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4162 R_Main_FreeViewCache();
4164 R_FrameData_Reset();
4167 void GL_Main_Init(void)
4169 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4171 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4172 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4173 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4174 if (gamemode == GAME_NEHAHRA)
4176 Cvar_RegisterVariable (&gl_fogenable);
4177 Cvar_RegisterVariable (&gl_fogdensity);
4178 Cvar_RegisterVariable (&gl_fogred);
4179 Cvar_RegisterVariable (&gl_foggreen);
4180 Cvar_RegisterVariable (&gl_fogblue);
4181 Cvar_RegisterVariable (&gl_fogstart);
4182 Cvar_RegisterVariable (&gl_fogend);
4183 Cvar_RegisterVariable (&gl_skyclip);
4185 Cvar_RegisterVariable(&r_motionblur);
4186 Cvar_RegisterVariable(&r_damageblur);
4187 Cvar_RegisterVariable(&r_motionblur_averaging);
4188 Cvar_RegisterVariable(&r_motionblur_randomize);
4189 Cvar_RegisterVariable(&r_motionblur_minblur);
4190 Cvar_RegisterVariable(&r_motionblur_maxblur);
4191 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4192 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4193 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4194 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4195 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4196 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4197 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4198 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4199 Cvar_RegisterVariable(&r_equalize_entities_by);
4200 Cvar_RegisterVariable(&r_equalize_entities_to);
4201 Cvar_RegisterVariable(&r_depthfirst);
4202 Cvar_RegisterVariable(&r_useinfinitefarclip);
4203 Cvar_RegisterVariable(&r_farclip_base);
4204 Cvar_RegisterVariable(&r_farclip_world);
4205 Cvar_RegisterVariable(&r_nearclip);
4206 Cvar_RegisterVariable(&r_deformvertexes);
4207 Cvar_RegisterVariable(&r_transparent);
4208 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4209 Cvar_RegisterVariable(&r_showoverdraw);
4210 Cvar_RegisterVariable(&r_showbboxes);
4211 Cvar_RegisterVariable(&r_showsurfaces);
4212 Cvar_RegisterVariable(&r_showtris);
4213 Cvar_RegisterVariable(&r_shownormals);
4214 Cvar_RegisterVariable(&r_showlighting);
4215 Cvar_RegisterVariable(&r_showshadowvolumes);
4216 Cvar_RegisterVariable(&r_showcollisionbrushes);
4217 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4218 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4219 Cvar_RegisterVariable(&r_showdisabledepthtest);
4220 Cvar_RegisterVariable(&r_drawportals);
4221 Cvar_RegisterVariable(&r_drawentities);
4222 Cvar_RegisterVariable(&r_draw2d);
4223 Cvar_RegisterVariable(&r_drawworld);
4224 Cvar_RegisterVariable(&r_cullentities_trace);
4225 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4226 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4227 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4228 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4229 Cvar_RegisterVariable(&r_sortentities);
4230 Cvar_RegisterVariable(&r_drawviewmodel);
4231 Cvar_RegisterVariable(&r_drawexteriormodel);
4232 Cvar_RegisterVariable(&r_speeds);
4233 Cvar_RegisterVariable(&r_fullbrights);
4234 Cvar_RegisterVariable(&r_wateralpha);
4235 Cvar_RegisterVariable(&r_dynamic);
4236 Cvar_RegisterVariable(&r_fakelight);
4237 Cvar_RegisterVariable(&r_fakelight_intensity);
4238 Cvar_RegisterVariable(&r_fullbright);
4239 Cvar_RegisterVariable(&r_shadows);
4240 Cvar_RegisterVariable(&r_shadows_darken);
4241 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4242 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4243 Cvar_RegisterVariable(&r_shadows_throwdistance);
4244 Cvar_RegisterVariable(&r_shadows_throwdirection);
4245 Cvar_RegisterVariable(&r_shadows_focus);
4246 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4247 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4248 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4249 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4250 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4251 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4252 Cvar_RegisterVariable(&r_fog_exp2);
4253 Cvar_RegisterVariable(&r_fog_clear);
4254 Cvar_RegisterVariable(&r_drawfog);
4255 Cvar_RegisterVariable(&r_transparentdepthmasking);
4256 Cvar_RegisterVariable(&r_transparent_sortmindist);
4257 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4258 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4259 Cvar_RegisterVariable(&r_texture_dds_load);
4260 Cvar_RegisterVariable(&r_texture_dds_save);
4261 Cvar_RegisterVariable(&r_textureunits);
4262 Cvar_RegisterVariable(&gl_combine);
4263 Cvar_RegisterVariable(&r_viewfbo);
4264 Cvar_RegisterVariable(&r_viewscale);
4265 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4266 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4267 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4268 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4269 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4270 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4271 Cvar_RegisterVariable(&r_glsl);
4272 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4273 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4274 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4275 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4276 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4277 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4278 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4279 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4280 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4281 Cvar_RegisterVariable(&r_glsl_postprocess);
4282 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4283 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4284 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4285 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4286 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4287 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4288 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4289 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4291 Cvar_RegisterVariable(&r_water);
4292 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4293 Cvar_RegisterVariable(&r_water_clippingplanebias);
4294 Cvar_RegisterVariable(&r_water_refractdistort);
4295 Cvar_RegisterVariable(&r_water_reflectdistort);
4296 Cvar_RegisterVariable(&r_water_scissormode);
4297 Cvar_RegisterVariable(&r_water_lowquality);
4299 Cvar_RegisterVariable(&r_lerpsprites);
4300 Cvar_RegisterVariable(&r_lerpmodels);
4301 Cvar_RegisterVariable(&r_lerplightstyles);
4302 Cvar_RegisterVariable(&r_waterscroll);
4303 Cvar_RegisterVariable(&r_bloom);
4304 Cvar_RegisterVariable(&r_bloom_colorscale);
4305 Cvar_RegisterVariable(&r_bloom_brighten);
4306 Cvar_RegisterVariable(&r_bloom_blur);
4307 Cvar_RegisterVariable(&r_bloom_resolution);
4308 Cvar_RegisterVariable(&r_bloom_colorexponent);
4309 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4310 Cvar_RegisterVariable(&r_hdr);
4311 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4312 Cvar_RegisterVariable(&r_hdr_glowintensity);
4313 Cvar_RegisterVariable(&r_hdr_range);
4314 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4315 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4316 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4317 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4318 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4319 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4320 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4321 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4322 Cvar_RegisterVariable(&developer_texturelogging);
4323 Cvar_RegisterVariable(&gl_lightmaps);
4324 Cvar_RegisterVariable(&r_test);
4325 Cvar_RegisterVariable(&r_glsl_saturation);
4326 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4327 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4328 Cvar_RegisterVariable(&r_framedatasize);
4329 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4330 Cvar_SetValue("r_fullbrights", 0);
4331 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4334 extern void R_Textures_Init(void);
4335 extern void GL_Draw_Init(void);
4336 extern void GL_Main_Init(void);
4337 extern void R_Shadow_Init(void);
4338 extern void R_Sky_Init(void);
4339 extern void GL_Surf_Init(void);
4340 extern void R_Particles_Init(void);
4341 extern void R_Explosion_Init(void);
4342 extern void gl_backend_init(void);
4343 extern void Sbar_Init(void);
4344 extern void R_LightningBeams_Init(void);
4345 extern void Mod_RenderInit(void);
4346 extern void Font_Init(void);
4348 void Render_Init(void)
4361 R_LightningBeams_Init();
4371 extern char *ENGINE_EXTENSIONS;
4374 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4375 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4376 gl_version = (const char *)qglGetString(GL_VERSION);
4377 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4381 if (!gl_platformextensions)
4382 gl_platformextensions = "";
4384 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4385 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4386 Con_Printf("GL_VERSION: %s\n", gl_version);
4387 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4388 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4390 VID_CheckExtensions();
4392 // LordHavoc: report supported extensions
4393 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4395 // clear to black (loading plaque will be seen over this)
4396 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4400 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4404 if (r_trippy.integer)
4406 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4408 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4411 p = r_refdef.view.frustum + i;
4416 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4420 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4424 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4428 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4432 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4436 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4440 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4444 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4452 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4456 if (r_trippy.integer)
4458 for (i = 0;i < numplanes;i++)
4465 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4469 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4473 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4477 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4481 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4485 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4489 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4493 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4501 //==================================================================================
4503 // LordHavoc: this stores temporary data used within the same frame
4505 typedef struct r_framedata_mem_s
4507 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4508 size_t size; // how much usable space
4509 size_t current; // how much space in use
4510 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4511 size_t wantedsize; // how much space was allocated
4512 unsigned char *data; // start of real data (16byte aligned)
4516 static r_framedata_mem_t *r_framedata_mem;
4518 void R_FrameData_Reset(void)
4520 while (r_framedata_mem)
4522 r_framedata_mem_t *next = r_framedata_mem->purge;
4523 Mem_Free(r_framedata_mem);
4524 r_framedata_mem = next;
4528 void R_FrameData_Resize(void)
4531 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4532 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4533 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4535 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4536 newmem->wantedsize = wantedsize;
4537 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4538 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4539 newmem->current = 0;
4541 newmem->purge = r_framedata_mem;
4542 r_framedata_mem = newmem;
4546 void R_FrameData_NewFrame(void)
4548 R_FrameData_Resize();
4549 if (!r_framedata_mem)
4551 // if we ran out of space on the last frame, free the old memory now
4552 while (r_framedata_mem->purge)
4554 // repeatedly remove the second item in the list, leaving only head
4555 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4556 Mem_Free(r_framedata_mem->purge);
4557 r_framedata_mem->purge = next;
4559 // reset the current mem pointer
4560 r_framedata_mem->current = 0;
4561 r_framedata_mem->mark = 0;
4564 void *R_FrameData_Alloc(size_t size)
4568 // align to 16 byte boundary - the data pointer is already aligned, so we
4569 // only need to ensure the size of every allocation is also aligned
4570 size = (size + 15) & ~15;
4572 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4574 // emergency - we ran out of space, allocate more memory
4575 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4576 R_FrameData_Resize();
4579 data = r_framedata_mem->data + r_framedata_mem->current;
4580 r_framedata_mem->current += size;
4582 // count the usage for stats
4583 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4584 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4586 return (void *)data;
4589 void *R_FrameData_Store(size_t size, void *data)
4591 void *d = R_FrameData_Alloc(size);
4593 memcpy(d, data, size);
4597 void R_FrameData_SetMark(void)
4599 if (!r_framedata_mem)
4601 r_framedata_mem->mark = r_framedata_mem->current;
4604 void R_FrameData_ReturnToMark(void)
4606 if (!r_framedata_mem)
4608 r_framedata_mem->current = r_framedata_mem->mark;
4611 //==================================================================================
4613 // LordHavoc: animcache originally written by Echon, rewritten since then
4616 * Animation cache prevents re-generating mesh data for an animated model
4617 * multiple times in one frame for lighting, shadowing, reflections, etc.
4620 void R_AnimCache_Free(void)
4624 void R_AnimCache_ClearCache(void)
4627 entity_render_t *ent;
4629 for (i = 0;i < r_refdef.scene.numentities;i++)
4631 ent = r_refdef.scene.entities[i];
4632 ent->animcache_vertex3f = NULL;
4633 ent->animcache_normal3f = NULL;
4634 ent->animcache_svector3f = NULL;
4635 ent->animcache_tvector3f = NULL;
4636 ent->animcache_vertexmesh = NULL;
4637 ent->animcache_vertex3fbuffer = NULL;
4638 ent->animcache_vertexmeshbuffer = NULL;
4642 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4646 // check if we need the meshbuffers
4647 if (!vid.useinterleavedarrays)
4650 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4651 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4652 // TODO: upload vertex3f buffer?
4653 if (ent->animcache_vertexmesh)
4655 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4656 for (i = 0;i < numvertices;i++)
4657 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4658 if (ent->animcache_svector3f)
4659 for (i = 0;i < numvertices;i++)
4660 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4661 if (ent->animcache_tvector3f)
4662 for (i = 0;i < numvertices;i++)
4663 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4664 if (ent->animcache_normal3f)
4665 for (i = 0;i < numvertices;i++)
4666 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4667 // TODO: upload vertexmeshbuffer?
4671 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4673 dp_model_t *model = ent->model;
4675 // see if it's already cached this frame
4676 if (ent->animcache_vertex3f)
4678 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4679 if (wantnormals || wanttangents)
4681 if (ent->animcache_normal3f)
4682 wantnormals = false;
4683 if (ent->animcache_svector3f)
4684 wanttangents = false;
4685 if (wantnormals || wanttangents)
4687 numvertices = model->surfmesh.num_vertices;
4689 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4692 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4693 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4695 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4696 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4702 // see if this ent is worth caching
4703 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4705 // get some memory for this entity and generate mesh data
4706 numvertices = model->surfmesh.num_vertices;
4707 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4709 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4712 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4713 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4715 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4716 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4721 void R_AnimCache_CacheVisibleEntities(void)
4724 qboolean wantnormals = true;
4725 qboolean wanttangents = !r_showsurfaces.integer;
4727 switch(vid.renderpath)
4729 case RENDERPATH_GL20:
4730 case RENDERPATH_D3D9:
4731 case RENDERPATH_D3D10:
4732 case RENDERPATH_D3D11:
4733 case RENDERPATH_GLES2:
4735 case RENDERPATH_GL11:
4736 case RENDERPATH_GL13:
4737 case RENDERPATH_GLES1:
4738 wanttangents = false;
4740 case RENDERPATH_SOFT:
4744 if (r_shownormals.integer)
4745 wanttangents = wantnormals = true;
4747 // TODO: thread this
4748 // NOTE: R_PrepareRTLights() also caches entities
4750 for (i = 0;i < r_refdef.scene.numentities;i++)
4751 if (r_refdef.viewcache.entityvisible[i])
4752 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4755 //==================================================================================
4757 extern cvar_t r_overheadsprites_pushback;
4759 static void R_View_UpdateEntityLighting (void)
4762 entity_render_t *ent;
4763 vec3_t tempdiffusenormal, avg;
4764 vec_t f, fa, fd, fdd;
4765 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4767 for (i = 0;i < r_refdef.scene.numentities;i++)
4769 ent = r_refdef.scene.entities[i];
4771 // skip unseen models
4772 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4776 if (ent->model && ent->model->brush.num_leafs)
4778 // TODO: use modellight for r_ambient settings on world?
4779 VectorSet(ent->modellight_ambient, 0, 0, 0);
4780 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4781 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4785 // fetch the lighting from the worldmodel data
4786 VectorClear(ent->modellight_ambient);
4787 VectorClear(ent->modellight_diffuse);
4788 VectorClear(tempdiffusenormal);
4789 if (ent->flags & RENDER_LIGHT)
4792 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4794 // complete lightning for lit sprites
4795 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4796 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4798 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4799 org[2] = org[2] + r_overheadsprites_pushback.value;
4800 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4803 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4805 if(ent->flags & RENDER_EQUALIZE)
4807 // first fix up ambient lighting...
4808 if(r_equalize_entities_minambient.value > 0)
4810 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4813 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4814 if(fa < r_equalize_entities_minambient.value * fd)
4817 // fa'/fd' = minambient
4818 // fa'+0.25*fd' = fa+0.25*fd
4820 // fa' = fd' * minambient
4821 // fd'*(0.25+minambient) = fa+0.25*fd
4823 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4824 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4826 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4827 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
4828 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4829 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4834 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4836 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4837 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4841 // adjust brightness and saturation to target
4842 avg[0] = avg[1] = avg[2] = fa / f;
4843 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4844 avg[0] = avg[1] = avg[2] = fd / f;
4845 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4851 VectorSet(ent->modellight_ambient, 1, 1, 1);
4853 // move the light direction into modelspace coordinates for lighting code
4854 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4855 if(VectorLength2(ent->modellight_lightdir) == 0)
4856 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4857 VectorNormalize(ent->modellight_lightdir);
4861 #define MAX_LINEOFSIGHTTRACES 64
4863 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4866 vec3_t boxmins, boxmaxs;
4869 dp_model_t *model = r_refdef.scene.worldmodel;
4871 if (!model || !model->brush.TraceLineOfSight)
4874 // expand the box a little
4875 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4876 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4877 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4878 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4879 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4880 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4882 // return true if eye is inside enlarged box
4883 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4887 VectorCopy(eye, start);
4888 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4889 if (model->brush.TraceLineOfSight(model, start, end))
4892 // try various random positions
4893 for (i = 0;i < numsamples;i++)
4895 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4896 if (model->brush.TraceLineOfSight(model, start, end))
4904 static void R_View_UpdateEntityVisible (void)
4909 entity_render_t *ent;
4911 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4912 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4913 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4914 : RENDER_EXTERIORMODEL;
4915 if (!r_drawviewmodel.integer)
4916 renderimask |= RENDER_VIEWMODEL;
4917 if (!r_drawexteriormodel.integer)
4918 renderimask |= RENDER_EXTERIORMODEL;
4919 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4921 // worldmodel can check visibility
4922 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4923 for (i = 0;i < r_refdef.scene.numentities;i++)
4925 ent = r_refdef.scene.entities[i];
4926 if (!(ent->flags & renderimask))
4927 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)))
4928 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))
4929 r_refdef.viewcache.entityvisible[i] = true;
4934 // no worldmodel or it can't check visibility
4935 for (i = 0;i < r_refdef.scene.numentities;i++)
4937 ent = r_refdef.scene.entities[i];
4938 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));
4941 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4942 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4944 for (i = 0;i < r_refdef.scene.numentities;i++)
4946 if (!r_refdef.viewcache.entityvisible[i])
4948 ent = r_refdef.scene.entities[i];
4949 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4951 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4953 continue; // temp entities do pvs only
4954 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4955 ent->last_trace_visibility = realtime;
4956 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4957 r_refdef.viewcache.entityvisible[i] = 0;
4963 /// only used if skyrendermasked, and normally returns false
4964 int R_DrawBrushModelsSky (void)
4967 entity_render_t *ent;
4970 for (i = 0;i < r_refdef.scene.numentities;i++)
4972 if (!r_refdef.viewcache.entityvisible[i])
4974 ent = r_refdef.scene.entities[i];
4975 if (!ent->model || !ent->model->DrawSky)
4977 ent->model->DrawSky(ent);
4983 static void R_DrawNoModel(entity_render_t *ent);
4984 static void R_DrawModels(void)
4987 entity_render_t *ent;
4989 for (i = 0;i < r_refdef.scene.numentities;i++)
4991 if (!r_refdef.viewcache.entityvisible[i])
4993 ent = r_refdef.scene.entities[i];
4994 r_refdef.stats.entities++;
4996 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4999 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5000 Con_Printf("R_DrawModels\n");
5001 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]);
5002 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);
5003 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);
5006 if (ent->model && ent->model->Draw != NULL)
5007 ent->model->Draw(ent);
5013 static void R_DrawModelsDepth(void)
5016 entity_render_t *ent;
5018 for (i = 0;i < r_refdef.scene.numentities;i++)
5020 if (!r_refdef.viewcache.entityvisible[i])
5022 ent = r_refdef.scene.entities[i];
5023 if (ent->model && ent->model->DrawDepth != NULL)
5024 ent->model->DrawDepth(ent);
5028 static void R_DrawModelsDebug(void)
5031 entity_render_t *ent;
5033 for (i = 0;i < r_refdef.scene.numentities;i++)
5035 if (!r_refdef.viewcache.entityvisible[i])
5037 ent = r_refdef.scene.entities[i];
5038 if (ent->model && ent->model->DrawDebug != NULL)
5039 ent->model->DrawDebug(ent);
5043 static void R_DrawModelsAddWaterPlanes(void)
5046 entity_render_t *ent;
5048 for (i = 0;i < r_refdef.scene.numentities;i++)
5050 if (!r_refdef.viewcache.entityvisible[i])
5052 ent = r_refdef.scene.entities[i];
5053 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5054 ent->model->DrawAddWaterPlanes(ent);
5058 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5060 if (r_hdr_irisadaptation.integer)
5064 vec3_t diffusenormal;
5068 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5069 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5070 brightness = max(0.0000001f, brightness);
5071 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5072 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5073 current = r_hdr_irisadaptation_value.value;
5075 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5076 else if (current > goal)
5077 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5078 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5079 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5081 else if (r_hdr_irisadaptation_value.value != 1.0f)
5082 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5085 static void R_View_SetFrustum(const int *scissor)
5088 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5089 vec3_t forward, left, up, origin, v;
5093 // flipped x coordinates (because x points left here)
5094 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5095 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5097 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5098 switch(vid.renderpath)
5100 case RENDERPATH_D3D9:
5101 case RENDERPATH_D3D10:
5102 case RENDERPATH_D3D11:
5103 // non-flipped y coordinates
5104 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5105 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5107 case RENDERPATH_SOFT:
5108 case RENDERPATH_GL11:
5109 case RENDERPATH_GL13:
5110 case RENDERPATH_GL20:
5111 case RENDERPATH_GLES1:
5112 case RENDERPATH_GLES2:
5113 // non-flipped y coordinates
5114 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5115 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5120 // we can't trust r_refdef.view.forward and friends in reflected scenes
5121 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5124 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5125 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5126 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5127 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5128 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5129 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5130 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5131 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5132 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5133 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5134 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5135 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5139 zNear = r_refdef.nearclip;
5140 nudge = 1.0 - 1.0 / (1<<23);
5141 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5142 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5143 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5144 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5145 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5146 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5147 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5148 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5154 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5155 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5156 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5157 r_refdef.view.frustum[0].dist = m[15] - m[12];
5159 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5160 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5161 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5162 r_refdef.view.frustum[1].dist = m[15] + m[12];
5164 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5165 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5166 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5167 r_refdef.view.frustum[2].dist = m[15] - m[13];
5169 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5170 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5171 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5172 r_refdef.view.frustum[3].dist = m[15] + m[13];
5174 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5175 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5176 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5177 r_refdef.view.frustum[4].dist = m[15] - m[14];
5179 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5180 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5181 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5182 r_refdef.view.frustum[5].dist = m[15] + m[14];
5185 if (r_refdef.view.useperspective)
5187 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5188 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]);
5189 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]);
5190 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]);
5191 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]);
5193 // then the normals from the corners relative to origin
5194 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5195 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5196 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5197 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5199 // in a NORMAL view, forward cross left == up
5200 // in a REFLECTED view, forward cross left == down
5201 // so our cross products above need to be adjusted for a left handed coordinate system
5202 CrossProduct(forward, left, v);
5203 if(DotProduct(v, up) < 0)
5205 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5206 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5207 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5208 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5211 // Leaving those out was a mistake, those were in the old code, and they
5212 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5213 // I couldn't reproduce it after adding those normalizations. --blub
5214 VectorNormalize(r_refdef.view.frustum[0].normal);
5215 VectorNormalize(r_refdef.view.frustum[1].normal);
5216 VectorNormalize(r_refdef.view.frustum[2].normal);
5217 VectorNormalize(r_refdef.view.frustum[3].normal);
5219 // make the corners absolute
5220 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5221 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5222 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5223 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5226 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5228 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5229 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5230 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5231 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5232 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5236 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5237 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5238 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5239 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5240 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5241 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5242 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5243 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5244 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5245 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5247 r_refdef.view.numfrustumplanes = 5;
5249 if (r_refdef.view.useclipplane)
5251 r_refdef.view.numfrustumplanes = 6;
5252 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5255 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5256 PlaneClassify(r_refdef.view.frustum + i);
5258 // LordHavoc: note to all quake engine coders, Quake had a special case
5259 // for 90 degrees which assumed a square view (wrong), so I removed it,
5260 // Quake2 has it disabled as well.
5262 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5263 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5264 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5265 //PlaneClassify(&frustum[0]);
5267 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5268 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5269 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5270 //PlaneClassify(&frustum[1]);
5272 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5273 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5274 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5275 //PlaneClassify(&frustum[2]);
5277 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5278 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5279 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5280 //PlaneClassify(&frustum[3]);
5283 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5284 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5285 //PlaneClassify(&frustum[4]);
5288 void R_View_UpdateWithScissor(const int *myscissor)
5290 R_Main_ResizeViewCache();
5291 R_View_SetFrustum(myscissor);
5292 R_View_WorldVisibility(r_refdef.view.useclipplane);
5293 R_View_UpdateEntityVisible();
5294 R_View_UpdateEntityLighting();
5297 void R_View_Update(void)
5299 R_Main_ResizeViewCache();
5300 R_View_SetFrustum(NULL);
5301 R_View_WorldVisibility(r_refdef.view.useclipplane);
5302 R_View_UpdateEntityVisible();
5303 R_View_UpdateEntityLighting();
5306 float viewscalefpsadjusted = 1.0f;
5308 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5310 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5311 scale = bound(0.03125f, scale, 1.0f);
5312 *outwidth = (int)ceil(width * scale);
5313 *outheight = (int)ceil(height * scale);
5316 void R_Mesh_SetMainRenderTargets(void)
5318 if (r_bloomstate.fbo_framebuffer)
5319 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5321 R_Mesh_ResetRenderTargets();
5324 void R_SetupView(qboolean allowwaterclippingplane)
5326 const float *customclipplane = NULL;
5328 int scaledwidth, scaledheight;
5329 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5331 // LordHavoc: couldn't figure out how to make this approach the
5332 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5333 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5334 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5335 dist = r_refdef.view.clipplane.dist;
5336 plane[0] = r_refdef.view.clipplane.normal[0];
5337 plane[1] = r_refdef.view.clipplane.normal[1];
5338 plane[2] = r_refdef.view.clipplane.normal[2];
5340 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5343 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5344 if (!r_refdef.view.useperspective)
5345 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);
5346 else if (vid.stencil && r_useinfinitefarclip.integer)
5347 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);
5349 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);
5350 R_Mesh_SetMainRenderTargets();
5351 R_SetViewport(&r_refdef.view.viewport);
5352 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5354 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5355 float screenplane[4];
5356 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5357 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5358 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5359 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5360 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5364 void R_EntityMatrix(const matrix4x4_t *matrix)
5366 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5368 gl_modelmatrixchanged = false;
5369 gl_modelmatrix = *matrix;
5370 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5371 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5372 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5373 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5375 switch(vid.renderpath)
5377 case RENDERPATH_D3D9:
5379 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5380 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5383 case RENDERPATH_D3D10:
5384 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5386 case RENDERPATH_D3D11:
5387 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5389 case RENDERPATH_GL11:
5390 case RENDERPATH_GL13:
5391 case RENDERPATH_GLES1:
5392 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5394 case RENDERPATH_SOFT:
5395 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5396 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5398 case RENDERPATH_GL20:
5399 case RENDERPATH_GLES2:
5400 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5401 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5407 void R_ResetViewRendering2D(void)
5409 r_viewport_t viewport;
5412 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5413 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);
5414 R_Mesh_ResetRenderTargets();
5415 R_SetViewport(&viewport);
5416 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5417 GL_Color(1, 1, 1, 1);
5418 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5419 GL_BlendFunc(GL_ONE, GL_ZERO);
5420 GL_ScissorTest(false);
5421 GL_DepthMask(false);
5422 GL_DepthRange(0, 1);
5423 GL_DepthTest(false);
5424 GL_DepthFunc(GL_LEQUAL);
5425 R_EntityMatrix(&identitymatrix);
5426 R_Mesh_ResetTextureState();
5427 GL_PolygonOffset(0, 0);
5428 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5429 switch(vid.renderpath)
5431 case RENDERPATH_GL11:
5432 case RENDERPATH_GL13:
5433 case RENDERPATH_GL20:
5434 case RENDERPATH_GLES1:
5435 case RENDERPATH_GLES2:
5436 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5438 case RENDERPATH_D3D9:
5439 case RENDERPATH_D3D10:
5440 case RENDERPATH_D3D11:
5441 case RENDERPATH_SOFT:
5444 GL_CullFace(GL_NONE);
5447 void R_ResetViewRendering3D(void)
5452 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5453 GL_Color(1, 1, 1, 1);
5454 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5455 GL_BlendFunc(GL_ONE, GL_ZERO);
5456 GL_ScissorTest(true);
5458 GL_DepthRange(0, 1);
5460 GL_DepthFunc(GL_LEQUAL);
5461 R_EntityMatrix(&identitymatrix);
5462 R_Mesh_ResetTextureState();
5463 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5464 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5465 switch(vid.renderpath)
5467 case RENDERPATH_GL11:
5468 case RENDERPATH_GL13:
5469 case RENDERPATH_GL20:
5470 case RENDERPATH_GLES1:
5471 case RENDERPATH_GLES2:
5472 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5474 case RENDERPATH_D3D9:
5475 case RENDERPATH_D3D10:
5476 case RENDERPATH_D3D11:
5477 case RENDERPATH_SOFT:
5480 GL_CullFace(r_refdef.view.cullface_back);
5485 R_RenderView_UpdateViewVectors
5488 static void R_RenderView_UpdateViewVectors(void)
5490 // break apart the view matrix into vectors for various purposes
5491 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5492 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5493 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5494 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5495 // make an inverted copy of the view matrix for tracking sprites
5496 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5499 void R_RenderScene(void);
5500 void R_RenderWaterPlanes(void);
5502 static void R_Water_StartFrame(void)
5505 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5506 r_waterstate_waterplane_t *p;
5508 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5511 switch(vid.renderpath)
5513 case RENDERPATH_GL20:
5514 case RENDERPATH_D3D9:
5515 case RENDERPATH_D3D10:
5516 case RENDERPATH_D3D11:
5517 case RENDERPATH_SOFT:
5518 case RENDERPATH_GLES2:
5520 case RENDERPATH_GL11:
5521 case RENDERPATH_GL13:
5522 case RENDERPATH_GLES1:
5526 // set waterwidth and waterheight to the water resolution that will be
5527 // used (often less than the screen resolution for faster rendering)
5528 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5530 // calculate desired texture sizes
5531 // can't use water if the card does not support the texture size
5532 if (!r_water.integer || r_showsurfaces.integer)
5533 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5534 else if (vid.support.arb_texture_non_power_of_two)
5536 texturewidth = waterwidth;
5537 textureheight = waterheight;
5538 camerawidth = waterwidth;
5539 cameraheight = waterheight;
5543 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5544 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5545 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5546 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5549 // allocate textures as needed
5550 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5552 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5553 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5555 if (p->texture_refraction)
5556 R_FreeTexture(p->texture_refraction);
5557 p->texture_refraction = NULL;
5558 if (p->texture_reflection)
5559 R_FreeTexture(p->texture_reflection);
5560 p->texture_reflection = NULL;
5561 if (p->texture_camera)
5562 R_FreeTexture(p->texture_camera);
5563 p->texture_camera = NULL;
5565 memset(&r_waterstate, 0, sizeof(r_waterstate));
5566 r_waterstate.texturewidth = texturewidth;
5567 r_waterstate.textureheight = textureheight;
5568 r_waterstate.camerawidth = camerawidth;
5569 r_waterstate.cameraheight = cameraheight;
5572 if (r_waterstate.texturewidth)
5574 int scaledwidth, scaledheight;
5576 r_waterstate.enabled = true;
5578 // when doing a reduced render (HDR) we want to use a smaller area
5579 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5580 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5581 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5583 // set up variables that will be used in shader setup
5584 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5585 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5586 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5587 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5590 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5591 r_waterstate.numwaterplanes = 0;
5594 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5596 int triangleindex, planeindex;
5602 r_waterstate_waterplane_t *p;
5603 texture_t *t = R_GetCurrentTexture(surface->texture);
5605 // just use the first triangle with a valid normal for any decisions
5606 VectorClear(normal);
5607 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5609 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5610 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5611 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5612 TriangleNormal(vert[0], vert[1], vert[2], normal);
5613 if (VectorLength2(normal) >= 0.001)
5617 VectorCopy(normal, plane.normal);
5618 VectorNormalize(plane.normal);
5619 plane.dist = DotProduct(vert[0], plane.normal);
5620 PlaneClassify(&plane);
5621 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5623 // skip backfaces (except if nocullface is set)
5624 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5626 VectorNegate(plane.normal, plane.normal);
5628 PlaneClassify(&plane);
5632 // find a matching plane if there is one
5633 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5634 if(p->camera_entity == t->camera_entity)
5635 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5637 if (planeindex >= r_waterstate.maxwaterplanes)
5638 return; // nothing we can do, out of planes
5640 // if this triangle does not fit any known plane rendered this frame, add one
5641 if (planeindex >= r_waterstate.numwaterplanes)
5643 // store the new plane
5644 r_waterstate.numwaterplanes++;
5646 // clear materialflags and pvs
5647 p->materialflags = 0;
5648 p->pvsvalid = false;
5649 p->camera_entity = t->camera_entity;
5650 VectorCopy(surface->mins, p->mins);
5651 VectorCopy(surface->maxs, p->maxs);
5656 p->mins[0] = min(p->mins[0], surface->mins[0]);
5657 p->mins[1] = min(p->mins[1], surface->mins[1]);
5658 p->mins[2] = min(p->mins[2], surface->mins[2]);
5659 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5660 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5661 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5663 // merge this surface's materialflags into the waterplane
5664 p->materialflags |= t->currentmaterialflags;
5665 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5667 // merge this surface's PVS into the waterplane
5668 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5669 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5670 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5672 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5678 extern cvar_t r_drawparticles;
5679 extern cvar_t r_drawdecals;
5681 static void R_Water_ProcessPlanes(void)
5684 r_refdef_view_t originalview;
5685 r_refdef_view_t myview;
5686 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;
5687 r_waterstate_waterplane_t *p;
5690 originalview = r_refdef.view;
5692 // lowquality hack, temporarily shut down some cvars and restore afterwards
5693 qualityreduction = r_water_lowquality.integer;
5694 if (qualityreduction > 0)
5696 if (qualityreduction >= 1)
5698 old_r_shadows = r_shadows.integer;
5699 old_r_worldrtlight = r_shadow_realtime_world.integer;
5700 old_r_dlight = r_shadow_realtime_dlight.integer;
5701 Cvar_SetValueQuick(&r_shadows, 0);
5702 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5703 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5705 if (qualityreduction >= 2)
5707 old_r_dynamic = r_dynamic.integer;
5708 old_r_particles = r_drawparticles.integer;
5709 old_r_decals = r_drawdecals.integer;
5710 Cvar_SetValueQuick(&r_dynamic, 0);
5711 Cvar_SetValueQuick(&r_drawparticles, 0);
5712 Cvar_SetValueQuick(&r_drawdecals, 0);
5716 // make sure enough textures are allocated
5717 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5719 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5721 if (!p->texture_refraction)
5722 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);
5723 if (!p->texture_refraction)
5726 else if (p->materialflags & MATERIALFLAG_CAMERA)
5728 if (!p->texture_camera)
5729 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);
5730 if (!p->texture_camera)
5734 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5736 if (!p->texture_reflection)
5737 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);
5738 if (!p->texture_reflection)
5744 r_refdef.view = originalview;
5745 r_refdef.view.showdebug = false;
5746 r_refdef.view.width = r_waterstate.waterwidth;
5747 r_refdef.view.height = r_waterstate.waterheight;
5748 r_refdef.view.useclipplane = true;
5749 myview = r_refdef.view;
5750 r_waterstate.renderingscene = true;
5751 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5753 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5755 r_refdef.view = myview;
5756 if(r_water_scissormode.integer)
5759 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5760 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5763 // render reflected scene and copy into texture
5764 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5765 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5766 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5767 r_refdef.view.clipplane = p->plane;
5768 // reverse the cullface settings for this render
5769 r_refdef.view.cullface_front = GL_FRONT;
5770 r_refdef.view.cullface_back = GL_BACK;
5771 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5773 r_refdef.view.usecustompvs = true;
5775 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5777 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5780 R_ResetViewRendering3D();
5781 R_ClearScreen(r_refdef.fogenabled);
5782 if(r_water_scissormode.integer & 2)
5783 R_View_UpdateWithScissor(myscissor);
5786 if(r_water_scissormode.integer & 1)
5787 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5790 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);
5793 // render the normal view scene and copy into texture
5794 // (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)
5795 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5797 r_refdef.view = myview;
5798 if(r_water_scissormode.integer)
5801 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5802 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5805 r_waterstate.renderingrefraction = true;
5807 r_refdef.view.clipplane = p->plane;
5808 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5809 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5811 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5813 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5814 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5815 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5816 R_RenderView_UpdateViewVectors();
5817 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5819 r_refdef.view.usecustompvs = true;
5820 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);
5824 PlaneClassify(&r_refdef.view.clipplane);
5826 R_ResetViewRendering3D();
5827 R_ClearScreen(r_refdef.fogenabled);
5828 if(r_water_scissormode.integer & 2)
5829 R_View_UpdateWithScissor(myscissor);
5832 if(r_water_scissormode.integer & 1)
5833 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5836 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);
5837 r_waterstate.renderingrefraction = false;
5839 else if (p->materialflags & MATERIALFLAG_CAMERA)
5841 r_refdef.view = myview;
5843 r_refdef.view.clipplane = p->plane;
5844 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5845 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5847 r_refdef.view.width = r_waterstate.camerawidth;
5848 r_refdef.view.height = r_waterstate.cameraheight;
5849 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5850 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5852 if(p->camera_entity)
5854 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5855 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5858 // note: all of the view is used for displaying... so
5859 // there is no use in scissoring
5861 // reverse the cullface settings for this render
5862 r_refdef.view.cullface_front = GL_FRONT;
5863 r_refdef.view.cullface_back = GL_BACK;
5864 // also reverse the view matrix
5865 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
5866 R_RenderView_UpdateViewVectors();
5867 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5869 r_refdef.view.usecustompvs = true;
5870 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);
5873 // camera needs no clipplane
5874 r_refdef.view.useclipplane = false;
5876 PlaneClassify(&r_refdef.view.clipplane);
5878 R_ResetViewRendering3D();
5879 R_ClearScreen(r_refdef.fogenabled);
5883 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);
5884 r_waterstate.renderingrefraction = false;
5888 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5889 r_waterstate.renderingscene = false;
5890 r_refdef.view = originalview;
5891 R_ResetViewRendering3D();
5892 R_ClearScreen(r_refdef.fogenabled);
5896 r_refdef.view = originalview;
5897 r_waterstate.renderingscene = false;
5898 Cvar_SetValueQuick(&r_water, 0);
5899 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5901 // lowquality hack, restore cvars
5902 if (qualityreduction > 0)
5904 if (qualityreduction >= 1)
5906 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5907 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5908 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5910 if (qualityreduction >= 2)
5912 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5913 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5914 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5919 void R_Bloom_StartFrame(void)
5921 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5922 int viewwidth, viewheight;
5925 if (r_viewscale_fpsscaling.integer)
5927 double actualframetime;
5928 double targetframetime;
5930 actualframetime = r_refdef.lastdrawscreentime;
5931 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5932 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5933 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5934 if (r_viewscale_fpsscaling_stepsize.value > 0)
5935 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5936 viewscalefpsadjusted += adjust;
5937 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5940 viewscalefpsadjusted = 1.0f;
5942 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5944 switch(vid.renderpath)
5946 case RENDERPATH_GL20:
5947 case RENDERPATH_D3D9:
5948 case RENDERPATH_D3D10:
5949 case RENDERPATH_D3D11:
5950 case RENDERPATH_SOFT:
5951 case RENDERPATH_GLES2:
5953 case RENDERPATH_GL11:
5954 case RENDERPATH_GL13:
5955 case RENDERPATH_GLES1:
5959 // set bloomwidth and bloomheight to the bloom resolution that will be
5960 // used (often less than the screen resolution for faster rendering)
5961 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5962 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5963 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5964 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5965 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5967 // calculate desired texture sizes
5968 if (vid.support.arb_texture_non_power_of_two)
5970 screentexturewidth = vid.width;
5971 screentextureheight = vid.height;
5972 bloomtexturewidth = r_bloomstate.bloomwidth;
5973 bloomtextureheight = r_bloomstate.bloomheight;
5977 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5978 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5979 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5980 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5983 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))
5985 Cvar_SetValueQuick(&r_hdr, 0);
5986 Cvar_SetValueQuick(&r_bloom, 0);
5987 Cvar_SetValueQuick(&r_motionblur, 0);
5988 Cvar_SetValueQuick(&r_damageblur, 0);
5991 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)
5992 screentexturewidth = screentextureheight = 0;
5993 if (!r_hdr.integer && !r_bloom.integer)
5994 bloomtexturewidth = bloomtextureheight = 0;
5996 textype = TEXTYPE_COLORBUFFER;
5997 switch (vid.renderpath)
5999 case RENDERPATH_GL20:
6000 case RENDERPATH_GLES2:
6001 if (vid.support.ext_framebuffer_object)
6003 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6004 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6007 case RENDERPATH_GL11:
6008 case RENDERPATH_GL13:
6009 case RENDERPATH_GLES1:
6010 case RENDERPATH_D3D9:
6011 case RENDERPATH_D3D10:
6012 case RENDERPATH_D3D11:
6013 case RENDERPATH_SOFT:
6017 // allocate textures as needed
6018 if (r_bloomstate.screentexturewidth != screentexturewidth
6019 || r_bloomstate.screentextureheight != screentextureheight
6020 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6021 || r_bloomstate.bloomtextureheight != bloomtextureheight
6022 || r_bloomstate.texturetype != textype
6023 || r_bloomstate.viewfbo != r_viewfbo.integer)
6025 if (r_bloomstate.texture_bloom)
6026 R_FreeTexture(r_bloomstate.texture_bloom);
6027 r_bloomstate.texture_bloom = NULL;
6028 if (r_bloomstate.texture_screen)
6029 R_FreeTexture(r_bloomstate.texture_screen);
6030 r_bloomstate.texture_screen = NULL;
6031 if (r_bloomstate.fbo_framebuffer)
6032 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6033 r_bloomstate.fbo_framebuffer = 0;
6034 if (r_bloomstate.texture_framebuffercolor)
6035 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6036 r_bloomstate.texture_framebuffercolor = NULL;
6037 if (r_bloomstate.texture_framebufferdepth)
6038 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6039 r_bloomstate.texture_framebufferdepth = NULL;
6040 r_bloomstate.screentexturewidth = screentexturewidth;
6041 r_bloomstate.screentextureheight = screentextureheight;
6042 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6043 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);
6044 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6046 // FIXME: choose depth bits based on a cvar
6047 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6048 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);
6049 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6050 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6052 // render depth into one texture and normalmap into the other
6056 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6057 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6058 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6059 if (status != GL_FRAMEBUFFER_COMPLETE)
6060 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6064 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6065 r_bloomstate.bloomtextureheight = bloomtextureheight;
6066 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6067 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);
6068 r_bloomstate.viewfbo = r_viewfbo.integer;
6069 r_bloomstate.texturetype = textype;
6072 // when doing a reduced render (HDR) we want to use a smaller area
6073 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6074 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6075 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6076 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6077 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6079 // set up a texcoord array for the full resolution screen image
6080 // (we have to keep this around to copy back during final render)
6081 r_bloomstate.screentexcoord2f[0] = 0;
6082 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6083 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6084 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6085 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6086 r_bloomstate.screentexcoord2f[5] = 0;
6087 r_bloomstate.screentexcoord2f[6] = 0;
6088 r_bloomstate.screentexcoord2f[7] = 0;
6090 // set up a texcoord array for the reduced resolution bloom image
6091 // (which will be additive blended over the screen image)
6092 r_bloomstate.bloomtexcoord2f[0] = 0;
6093 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6094 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6095 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6096 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6097 r_bloomstate.bloomtexcoord2f[5] = 0;
6098 r_bloomstate.bloomtexcoord2f[6] = 0;
6099 r_bloomstate.bloomtexcoord2f[7] = 0;
6101 switch(vid.renderpath)
6103 case RENDERPATH_GL11:
6104 case RENDERPATH_GL13:
6105 case RENDERPATH_GL20:
6106 case RENDERPATH_SOFT:
6107 case RENDERPATH_GLES1:
6108 case RENDERPATH_GLES2:
6110 case RENDERPATH_D3D9:
6111 case RENDERPATH_D3D10:
6112 case RENDERPATH_D3D11:
6115 for (i = 0;i < 4;i++)
6117 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6118 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6119 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6120 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6126 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6128 r_bloomstate.enabled = true;
6129 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6132 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);
6134 if (r_bloomstate.fbo_framebuffer)
6135 r_refdef.view.clear = true;
6138 void R_Bloom_CopyBloomTexture(float colorscale)
6140 r_refdef.stats.bloom++;
6142 // scale down screen texture to the bloom texture size
6144 R_Mesh_SetMainRenderTargets();
6145 R_SetViewport(&r_bloomstate.viewport);
6146 GL_BlendFunc(GL_ONE, GL_ZERO);
6147 GL_Color(colorscale, colorscale, colorscale, 1);
6148 // 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...
6149 switch(vid.renderpath)
6151 case RENDERPATH_GL11:
6152 case RENDERPATH_GL13:
6153 case RENDERPATH_GL20:
6154 case RENDERPATH_GLES1:
6155 case RENDERPATH_GLES2:
6156 case RENDERPATH_SOFT:
6157 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6159 case RENDERPATH_D3D9:
6160 case RENDERPATH_D3D10:
6161 case RENDERPATH_D3D11:
6162 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6165 // TODO: do boxfilter scale-down in shader?
6166 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6167 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6168 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6170 // we now have a bloom image in the framebuffer
6171 // copy it into the bloom image texture for later processing
6172 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);
6173 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6176 void R_Bloom_CopyHDRTexture(void)
6178 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);
6179 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6182 void R_Bloom_MakeTexture(void)
6185 float xoffset, yoffset, r, brighten;
6187 r_refdef.stats.bloom++;
6189 R_ResetViewRendering2D();
6191 // we have a bloom image in the framebuffer
6193 R_SetViewport(&r_bloomstate.viewport);
6195 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6198 r = bound(0, r_bloom_colorexponent.value / x, 1);
6199 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6201 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6202 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6203 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6204 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6206 // copy the vertically blurred bloom view to a texture
6207 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);
6208 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6211 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6212 brighten = r_bloom_brighten.value;
6213 if (r_bloomstate.hdr)
6214 brighten *= r_hdr_range.value;
6215 brighten = sqrt(brighten);
6217 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6218 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6220 for (dir = 0;dir < 2;dir++)
6222 // blend on at multiple vertical offsets to achieve a vertical blur
6223 // TODO: do offset blends using GLSL
6224 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6225 GL_BlendFunc(GL_ONE, GL_ZERO);
6226 for (x = -range;x <= range;x++)
6228 if (!dir){xoffset = 0;yoffset = x;}
6229 else {xoffset = x;yoffset = 0;}
6230 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6231 yoffset /= (float)r_bloomstate.bloomtextureheight;
6232 // compute a texcoord array with the specified x and y offset
6233 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6234 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6235 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6236 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6237 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6238 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6239 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6240 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6241 // this r value looks like a 'dot' particle, fading sharply to
6242 // black at the edges
6243 // (probably not realistic but looks good enough)
6244 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6245 //r = brighten/(range*2+1);
6246 r = brighten / (range * 2 + 1);
6248 r *= (1 - x*x/(float)(range*range));
6249 GL_Color(r, r, r, 1);
6250 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6251 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6252 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6253 GL_BlendFunc(GL_ONE, GL_ONE);
6256 // copy the vertically blurred bloom view to a texture
6257 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);
6258 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6262 void R_HDR_RenderBloomTexture(void)
6264 int oldwidth, oldheight;
6265 float oldcolorscale;
6266 qboolean oldwaterstate;
6268 oldwaterstate = r_waterstate.enabled;
6269 oldcolorscale = r_refdef.view.colorscale;
6270 oldwidth = r_refdef.view.width;
6271 oldheight = r_refdef.view.height;
6272 r_refdef.view.width = r_bloomstate.bloomwidth;
6273 r_refdef.view.height = r_bloomstate.bloomheight;
6275 if(r_hdr.integer < 2)
6276 r_waterstate.enabled = false;
6278 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6279 // TODO: add exposure compensation features
6280 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6282 r_refdef.view.showdebug = false;
6283 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6285 R_ResetViewRendering3D();
6287 R_ClearScreen(r_refdef.fogenabled);
6288 if (r_timereport_active)
6289 R_TimeReport("HDRclear");
6292 if (r_timereport_active)
6293 R_TimeReport("visibility");
6295 // only do secondary renders with HDR if r_hdr is 2 or higher
6296 r_waterstate.numwaterplanes = 0;
6297 if (r_waterstate.enabled)
6298 R_RenderWaterPlanes();
6300 r_refdef.view.showdebug = true;
6302 r_waterstate.numwaterplanes = 0;
6304 R_ResetViewRendering2D();
6306 R_Bloom_CopyHDRTexture();
6307 R_Bloom_MakeTexture();
6309 // restore the view settings
6310 r_waterstate.enabled = oldwaterstate;
6311 r_refdef.view.width = oldwidth;
6312 r_refdef.view.height = oldheight;
6313 r_refdef.view.colorscale = oldcolorscale;
6315 R_ResetViewRendering3D();
6317 R_ClearScreen(r_refdef.fogenabled);
6318 if (r_timereport_active)
6319 R_TimeReport("viewclear");
6322 static void R_BlendView(void)
6324 unsigned int permutation;
6325 float uservecs[4][4];
6327 switch (vid.renderpath)
6329 case RENDERPATH_GL20:
6330 case RENDERPATH_D3D9:
6331 case RENDERPATH_D3D10:
6332 case RENDERPATH_D3D11:
6333 case RENDERPATH_SOFT:
6334 case RENDERPATH_GLES2:
6336 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6337 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6338 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6339 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6340 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6342 if (r_bloomstate.texture_screen)
6344 // make sure the buffer is available
6345 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6347 R_ResetViewRendering2D();
6348 R_Mesh_SetMainRenderTargets();
6350 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6352 // declare variables
6353 float blur_factor, blur_mouseaccel, blur_velocity;
6354 static float blur_average;
6355 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6357 // set a goal for the factoring
6358 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6359 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6360 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6361 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6362 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6363 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6365 // from the goal, pick an averaged value between goal and last value
6366 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6367 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6369 // enforce minimum amount of blur
6370 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6372 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6374 // calculate values into a standard alpha
6375 cl.motionbluralpha = 1 - exp(-
6377 (r_motionblur.value * blur_factor / 80)
6379 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6382 max(0.0001, cl.time - cl.oldtime) // fps independent
6385 // randomization for the blur value to combat persistent ghosting
6386 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6387 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6390 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6392 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6393 GL_Color(1, 1, 1, cl.motionbluralpha);
6394 switch(vid.renderpath)
6396 case RENDERPATH_GL11:
6397 case RENDERPATH_GL13:
6398 case RENDERPATH_GL20:
6399 case RENDERPATH_GLES1:
6400 case RENDERPATH_GLES2:
6401 case RENDERPATH_SOFT:
6402 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6404 case RENDERPATH_D3D9:
6405 case RENDERPATH_D3D10:
6406 case RENDERPATH_D3D11:
6407 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6410 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6411 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6412 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6415 // updates old view angles for next pass
6416 VectorCopy(cl.viewangles, blur_oldangles);
6419 // copy view into the screen texture
6420 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);
6421 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6423 else if (!r_bloomstate.texture_bloom)
6425 // we may still have to do view tint...
6426 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6428 // apply a color tint to the whole view
6429 R_ResetViewRendering2D();
6430 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6431 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6432 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6433 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6434 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6436 break; // no screen processing, no bloom, skip it
6439 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6441 // render simple bloom effect
6442 // copy the screen and shrink it and darken it for the bloom process
6443 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6444 // make the bloom texture
6445 R_Bloom_MakeTexture();
6448 #if _MSC_VER >= 1400
6449 #define sscanf sscanf_s
6451 memset(uservecs, 0, sizeof(uservecs));
6452 if (r_glsl_postprocess_uservec1_enable.integer)
6453 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6454 if (r_glsl_postprocess_uservec2_enable.integer)
6455 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6456 if (r_glsl_postprocess_uservec3_enable.integer)
6457 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6458 if (r_glsl_postprocess_uservec4_enable.integer)
6459 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6461 R_ResetViewRendering2D();
6462 GL_Color(1, 1, 1, 1);
6463 GL_BlendFunc(GL_ONE, GL_ZERO);
6465 switch(vid.renderpath)
6467 case RENDERPATH_GL20:
6468 case RENDERPATH_GLES2:
6469 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6470 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6471 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6472 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6473 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6474 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]);
6475 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6476 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]);
6477 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]);
6478 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]);
6479 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]);
6480 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6481 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6482 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);
6484 case RENDERPATH_D3D9:
6486 // 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...
6487 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6488 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6489 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6490 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6491 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6492 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6493 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6494 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6495 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6496 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6497 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6498 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6499 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6500 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6503 case RENDERPATH_D3D10:
6504 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6506 case RENDERPATH_D3D11:
6507 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6509 case RENDERPATH_SOFT:
6510 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6511 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6512 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6513 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6514 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6515 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6516 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6517 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6518 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6519 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6520 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6521 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6522 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6523 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6528 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6529 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6531 case RENDERPATH_GL11:
6532 case RENDERPATH_GL13:
6533 case RENDERPATH_GLES1:
6534 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6536 // apply a color tint to the whole view
6537 R_ResetViewRendering2D();
6538 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6539 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6540 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6541 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6542 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6548 matrix4x4_t r_waterscrollmatrix;
6550 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6553 if (gamemode == GAME_NEHAHRA)
6555 if (gl_fogenable.integer)
6557 r_refdef.oldgl_fogenable = true;
6558 r_refdef.fog_density = gl_fogdensity.value;
6559 r_refdef.fog_red = gl_fogred.value;
6560 r_refdef.fog_green = gl_foggreen.value;
6561 r_refdef.fog_blue = gl_fogblue.value;
6562 r_refdef.fog_alpha = 1;
6563 r_refdef.fog_start = 0;
6564 r_refdef.fog_end = gl_skyclip.value;
6565 r_refdef.fog_height = 1<<30;
6566 r_refdef.fog_fadedepth = 128;
6568 else if (r_refdef.oldgl_fogenable)
6570 r_refdef.oldgl_fogenable = false;
6571 r_refdef.fog_density = 0;
6572 r_refdef.fog_red = 0;
6573 r_refdef.fog_green = 0;
6574 r_refdef.fog_blue = 0;
6575 r_refdef.fog_alpha = 0;
6576 r_refdef.fog_start = 0;
6577 r_refdef.fog_end = 0;
6578 r_refdef.fog_height = 1<<30;
6579 r_refdef.fog_fadedepth = 128;
6584 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6585 r_refdef.fog_start = max(0, r_refdef.fog_start);
6586 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6588 if (r_refdef.fog_density && r_drawfog.integer)
6590 r_refdef.fogenabled = true;
6591 // this is the point where the fog reaches 0.9986 alpha, which we
6592 // consider a good enough cutoff point for the texture
6593 // (0.9986 * 256 == 255.6)
6594 if (r_fog_exp2.integer)
6595 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6597 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6598 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6599 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6600 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6601 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6602 R_BuildFogHeightTexture();
6603 // fog color was already set
6604 // update the fog texture
6605 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)
6606 R_BuildFogTexture();
6607 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6608 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6611 r_refdef.fogenabled = false;
6614 if (r_refdef.fog_density)
6616 r_refdef.fogcolor[0] = r_refdef.fog_red;
6617 r_refdef.fogcolor[1] = r_refdef.fog_green;
6618 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6620 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6621 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6622 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6623 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6627 VectorCopy(r_refdef.fogcolor, fogvec);
6628 // color.rgb *= ContrastBoost * SceneBrightness;
6629 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6630 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6631 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6632 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6637 void R_UpdateVariables(void)
6641 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6643 r_refdef.farclip = r_farclip_base.value;
6644 if (r_refdef.scene.worldmodel)
6645 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6646 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6648 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6649 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6650 r_refdef.polygonfactor = 0;
6651 r_refdef.polygonoffset = 0;
6652 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6653 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6655 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6656 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6657 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6658 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6659 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6660 if (FAKELIGHT_ENABLED)
6662 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6664 if (r_showsurfaces.integer)
6666 r_refdef.scene.rtworld = false;
6667 r_refdef.scene.rtworldshadows = false;
6668 r_refdef.scene.rtdlight = false;
6669 r_refdef.scene.rtdlightshadows = false;
6670 r_refdef.lightmapintensity = 0;
6673 switch(vid.renderpath)
6675 case RENDERPATH_GL20:
6676 case RENDERPATH_D3D9:
6677 case RENDERPATH_D3D10:
6678 case RENDERPATH_D3D11:
6679 case RENDERPATH_SOFT:
6680 case RENDERPATH_GLES2:
6681 if(v_glslgamma.integer && !vid_gammatables_trivial)
6683 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6685 // build GLSL gamma texture
6686 #define RAMPWIDTH 256
6687 unsigned short ramp[RAMPWIDTH * 3];
6688 unsigned char rampbgr[RAMPWIDTH][4];
6691 r_texture_gammaramps_serial = vid_gammatables_serial;
6693 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6694 for(i = 0; i < RAMPWIDTH; ++i)
6696 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6697 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6698 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6701 if (r_texture_gammaramps)
6703 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6707 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6713 // remove GLSL gamma texture
6716 case RENDERPATH_GL11:
6717 case RENDERPATH_GL13:
6718 case RENDERPATH_GLES1:
6723 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6724 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6730 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6731 if( scenetype != r_currentscenetype ) {
6732 // store the old scenetype
6733 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6734 r_currentscenetype = scenetype;
6735 // move in the new scene
6736 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6745 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6747 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6748 if( scenetype == r_currentscenetype ) {
6749 return &r_refdef.scene;
6751 return &r_scenes_store[ scenetype ];
6755 int R_SortEntities_Compare(const void *ap, const void *bp)
6757 const entity_render_t *a = *(const entity_render_t **)ap;
6758 const entity_render_t *b = *(const entity_render_t **)bp;
6761 if(a->model < b->model)
6763 if(a->model > b->model)
6767 // TODO possibly calculate the REAL skinnum here first using
6769 if(a->skinnum < b->skinnum)
6771 if(a->skinnum > b->skinnum)
6774 // everything we compared is equal
6777 void R_SortEntities(void)
6779 // below or equal 2 ents, sorting never gains anything
6780 if(r_refdef.scene.numentities <= 2)
6783 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6791 int dpsoftrast_test;
6792 extern void R_Shadow_UpdateBounceGridTexture(void);
6793 extern cvar_t r_shadow_bouncegrid;
6794 void R_RenderView(void)
6796 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6798 dpsoftrast_test = r_test.integer;
6800 if (r_timereport_active)
6801 R_TimeReport("start");
6802 r_textureframe++; // used only by R_GetCurrentTexture
6803 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6805 if(R_CompileShader_CheckStaticParms())
6808 if (!r_drawentities.integer)
6809 r_refdef.scene.numentities = 0;
6810 else if (r_sortentities.integer)
6813 R_AnimCache_ClearCache();
6814 R_FrameData_NewFrame();
6816 /* adjust for stereo display */
6817 if(R_Stereo_Active())
6819 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);
6820 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6823 if (r_refdef.view.isoverlay)
6825 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6826 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6827 R_TimeReport("depthclear");
6829 r_refdef.view.showdebug = false;
6831 r_waterstate.enabled = false;
6832 r_waterstate.numwaterplanes = 0;
6836 r_refdef.view.matrix = originalmatrix;
6842 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6844 r_refdef.view.matrix = originalmatrix;
6845 return; //Host_Error ("R_RenderView: NULL worldmodel");
6848 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6850 R_RenderView_UpdateViewVectors();
6852 R_Shadow_UpdateWorldLightSelection();
6854 R_Bloom_StartFrame();
6855 R_Water_StartFrame();
6858 if (r_timereport_active)
6859 R_TimeReport("viewsetup");
6861 R_ResetViewRendering3D();
6863 if (r_refdef.view.clear || r_refdef.fogenabled)
6865 R_ClearScreen(r_refdef.fogenabled);
6866 if (r_timereport_active)
6867 R_TimeReport("viewclear");
6869 r_refdef.view.clear = true;
6871 // this produces a bloom texture to be used in R_BlendView() later
6872 if (r_bloomstate.hdr)
6874 R_HDR_RenderBloomTexture();
6875 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6876 r_textureframe++; // used only by R_GetCurrentTexture
6879 r_refdef.view.showdebug = true;
6882 if (r_timereport_active)
6883 R_TimeReport("visibility");
6885 R_Shadow_UpdateBounceGridTexture();
6886 if (r_timereport_active && r_shadow_bouncegrid.integer)
6887 R_TimeReport("bouncegrid");
6889 r_waterstate.numwaterplanes = 0;
6890 if (r_waterstate.enabled)
6891 R_RenderWaterPlanes();
6894 r_waterstate.numwaterplanes = 0;
6897 if (r_timereport_active)
6898 R_TimeReport("blendview");
6900 GL_Scissor(0, 0, vid.width, vid.height);
6901 GL_ScissorTest(false);
6903 r_refdef.view.matrix = originalmatrix;
6908 void R_RenderWaterPlanes(void)
6910 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6912 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6913 if (r_timereport_active)
6914 R_TimeReport("waterworld");
6917 // don't let sound skip if going slow
6918 if (r_refdef.scene.extraupdate)
6921 R_DrawModelsAddWaterPlanes();
6922 if (r_timereport_active)
6923 R_TimeReport("watermodels");
6925 if (r_waterstate.numwaterplanes)
6927 R_Water_ProcessPlanes();
6928 if (r_timereport_active)
6929 R_TimeReport("waterscenes");
6933 extern void R_DrawLightningBeams (void);
6934 extern void VM_CL_AddPolygonsToMeshQueue (void);
6935 extern void R_DrawPortals (void);
6936 extern cvar_t cl_locs_show;
6937 static void R_DrawLocs(void);
6938 static void R_DrawEntityBBoxes(void);
6939 static void R_DrawModelDecals(void);
6940 extern void R_DrawModelShadows(void);
6941 extern void R_DrawModelShadowMaps(void);
6942 extern cvar_t cl_decals_newsystem;
6943 extern qboolean r_shadow_usingdeferredprepass;
6944 void R_RenderScene(void)
6946 qboolean shadowmapping = false;
6948 if (r_timereport_active)
6949 R_TimeReport("beginscene");
6951 r_refdef.stats.renders++;
6955 // don't let sound skip if going slow
6956 if (r_refdef.scene.extraupdate)
6959 R_MeshQueue_BeginScene();
6963 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);
6965 if (r_timereport_active)
6966 R_TimeReport("skystartframe");
6968 if (cl.csqc_vidvars.drawworld)
6970 // don't let sound skip if going slow
6971 if (r_refdef.scene.extraupdate)
6974 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6976 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6977 if (r_timereport_active)
6978 R_TimeReport("worldsky");
6981 if (R_DrawBrushModelsSky() && r_timereport_active)
6982 R_TimeReport("bmodelsky");
6984 if (skyrendermasked && skyrenderlater)
6986 // we have to force off the water clipping plane while rendering sky
6990 if (r_timereport_active)
6991 R_TimeReport("sky");
6995 R_AnimCache_CacheVisibleEntities();
6996 if (r_timereport_active)
6997 R_TimeReport("animation");
6999 R_Shadow_PrepareLights();
7000 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7001 R_Shadow_PrepareModelShadows();
7002 if (r_timereport_active)
7003 R_TimeReport("preparelights");
7005 if (R_Shadow_ShadowMappingEnabled())
7006 shadowmapping = true;
7008 if (r_shadow_usingdeferredprepass)
7009 R_Shadow_DrawPrepass();
7011 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7013 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7014 if (r_timereport_active)
7015 R_TimeReport("worlddepth");
7017 if (r_depthfirst.integer >= 2)
7019 R_DrawModelsDepth();
7020 if (r_timereport_active)
7021 R_TimeReport("modeldepth");
7024 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7026 R_DrawModelShadowMaps();
7027 R_ResetViewRendering3D();
7028 // don't let sound skip if going slow
7029 if (r_refdef.scene.extraupdate)
7033 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7035 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7036 if (r_timereport_active)
7037 R_TimeReport("world");
7040 // don't let sound skip if going slow
7041 if (r_refdef.scene.extraupdate)
7045 if (r_timereport_active)
7046 R_TimeReport("models");
7048 // don't let sound skip if going slow
7049 if (r_refdef.scene.extraupdate)
7052 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7054 R_DrawModelShadows();
7055 R_ResetViewRendering3D();
7056 // don't let sound skip if going slow
7057 if (r_refdef.scene.extraupdate)
7061 if (!r_shadow_usingdeferredprepass)
7063 R_Shadow_DrawLights();
7064 if (r_timereport_active)
7065 R_TimeReport("rtlights");
7068 // don't let sound skip if going slow
7069 if (r_refdef.scene.extraupdate)
7072 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7074 R_DrawModelShadows();
7075 R_ResetViewRendering3D();
7076 // don't let sound skip if going slow
7077 if (r_refdef.scene.extraupdate)
7081 if (cl.csqc_vidvars.drawworld)
7083 if (cl_decals_newsystem.integer)
7085 R_DrawModelDecals();
7086 if (r_timereport_active)
7087 R_TimeReport("modeldecals");
7092 if (r_timereport_active)
7093 R_TimeReport("decals");
7097 if (r_timereport_active)
7098 R_TimeReport("particles");
7101 if (r_timereport_active)
7102 R_TimeReport("explosions");
7104 R_DrawLightningBeams();
7105 if (r_timereport_active)
7106 R_TimeReport("lightning");
7109 VM_CL_AddPolygonsToMeshQueue();
7111 if (r_refdef.view.showdebug)
7113 if (cl_locs_show.integer)
7116 if (r_timereport_active)
7117 R_TimeReport("showlocs");
7120 if (r_drawportals.integer)
7123 if (r_timereport_active)
7124 R_TimeReport("portals");
7127 if (r_showbboxes.value > 0)
7129 R_DrawEntityBBoxes();
7130 if (r_timereport_active)
7131 R_TimeReport("bboxes");
7135 if (r_transparent.integer)
7137 R_MeshQueue_RenderTransparent();
7138 if (r_timereport_active)
7139 R_TimeReport("drawtrans");
7142 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))
7144 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7145 if (r_timereport_active)
7146 R_TimeReport("worlddebug");
7147 R_DrawModelsDebug();
7148 if (r_timereport_active)
7149 R_TimeReport("modeldebug");
7152 if (cl.csqc_vidvars.drawworld)
7154 R_Shadow_DrawCoronas();
7155 if (r_timereport_active)
7156 R_TimeReport("coronas");
7161 GL_DepthTest(false);
7162 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7163 GL_Color(1, 1, 1, 1);
7164 qglBegin(GL_POLYGON);
7165 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7166 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7167 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7168 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7170 qglBegin(GL_POLYGON);
7171 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]);
7172 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]);
7173 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]);
7174 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]);
7176 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7180 // don't let sound skip if going slow
7181 if (r_refdef.scene.extraupdate)
7184 R_ResetViewRendering2D();
7187 static const unsigned short bboxelements[36] =
7197 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7200 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7202 RSurf_ActiveWorldEntity();
7204 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7205 GL_DepthMask(false);
7206 GL_DepthRange(0, 1);
7207 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7208 // R_Mesh_ResetTextureState();
7210 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7211 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7212 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7213 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7214 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7215 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7216 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7217 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7218 R_FillColors(color4f, 8, cr, cg, cb, ca);
7219 if (r_refdef.fogenabled)
7221 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7223 f1 = RSurf_FogVertex(v);
7225 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7226 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7227 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7230 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7231 R_Mesh_ResetTextureState();
7232 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7233 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7236 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7240 prvm_edict_t *edict;
7241 prvm_prog_t *prog_save = prog;
7243 // this function draws bounding boxes of server entities
7247 GL_CullFace(GL_NONE);
7248 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7252 for (i = 0;i < numsurfaces;i++)
7254 edict = PRVM_EDICT_NUM(surfacelist[i]);
7255 switch ((int)PRVM_serveredictfloat(edict, solid))
7257 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7258 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7259 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7260 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7261 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7262 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7264 color[3] *= r_showbboxes.value;
7265 color[3] = bound(0, color[3], 1);
7266 GL_DepthTest(!r_showdisabledepthtest.integer);
7267 GL_CullFace(r_refdef.view.cullface_front);
7268 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7274 static void R_DrawEntityBBoxes(void)
7277 prvm_edict_t *edict;
7279 prvm_prog_t *prog_save = prog;
7281 // this function draws bounding boxes of server entities
7287 for (i = 0;i < prog->num_edicts;i++)
7289 edict = PRVM_EDICT_NUM(i);
7290 if (edict->priv.server->free)
7292 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7293 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7295 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7297 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7298 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7304 static const int nomodelelement3i[24] =
7316 static const unsigned short nomodelelement3s[24] =
7328 static const float nomodelvertex3f[6*3] =
7338 static const float nomodelcolor4f[6*4] =
7340 0.0f, 0.0f, 0.5f, 1.0f,
7341 0.0f, 0.0f, 0.5f, 1.0f,
7342 0.0f, 0.5f, 0.0f, 1.0f,
7343 0.0f, 0.5f, 0.0f, 1.0f,
7344 0.5f, 0.0f, 0.0f, 1.0f,
7345 0.5f, 0.0f, 0.0f, 1.0f
7348 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7354 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);
7356 // this is only called once per entity so numsurfaces is always 1, and
7357 // surfacelist is always {0}, so this code does not handle batches
7359 if (rsurface.ent_flags & RENDER_ADDITIVE)
7361 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7362 GL_DepthMask(false);
7364 else if (rsurface.colormod[3] < 1)
7366 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7367 GL_DepthMask(false);
7371 GL_BlendFunc(GL_ONE, GL_ZERO);
7374 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7375 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7376 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7377 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7378 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7379 for (i = 0, c = color4f;i < 6;i++, c += 4)
7381 c[0] *= rsurface.colormod[0];
7382 c[1] *= rsurface.colormod[1];
7383 c[2] *= rsurface.colormod[2];
7384 c[3] *= rsurface.colormod[3];
7386 if (r_refdef.fogenabled)
7388 for (i = 0, c = color4f;i < 6;i++, c += 4)
7390 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7392 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7393 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7394 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7397 // R_Mesh_ResetTextureState();
7398 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7399 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7400 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7403 void R_DrawNoModel(entity_render_t *ent)
7406 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7407 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7408 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7410 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7413 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7415 vec3_t right1, right2, diff, normal;
7417 VectorSubtract (org2, org1, normal);
7419 // calculate 'right' vector for start
7420 VectorSubtract (r_refdef.view.origin, org1, diff);
7421 CrossProduct (normal, diff, right1);
7422 VectorNormalize (right1);
7424 // calculate 'right' vector for end
7425 VectorSubtract (r_refdef.view.origin, org2, diff);
7426 CrossProduct (normal, diff, right2);
7427 VectorNormalize (right2);
7429 vert[ 0] = org1[0] + width * right1[0];
7430 vert[ 1] = org1[1] + width * right1[1];
7431 vert[ 2] = org1[2] + width * right1[2];
7432 vert[ 3] = org1[0] - width * right1[0];
7433 vert[ 4] = org1[1] - width * right1[1];
7434 vert[ 5] = org1[2] - width * right1[2];
7435 vert[ 6] = org2[0] - width * right2[0];
7436 vert[ 7] = org2[1] - width * right2[1];
7437 vert[ 8] = org2[2] - width * right2[2];
7438 vert[ 9] = org2[0] + width * right2[0];
7439 vert[10] = org2[1] + width * right2[1];
7440 vert[11] = org2[2] + width * right2[2];
7443 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)
7445 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7446 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7447 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7448 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7449 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7450 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7451 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7452 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7453 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7454 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7455 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7456 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7459 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7464 VectorSet(v, x, y, z);
7465 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7466 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7468 if (i == mesh->numvertices)
7470 if (mesh->numvertices < mesh->maxvertices)
7472 VectorCopy(v, vertex3f);
7473 mesh->numvertices++;
7475 return mesh->numvertices;
7481 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7485 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7486 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7487 e = mesh->element3i + mesh->numtriangles * 3;
7488 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7490 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7491 if (mesh->numtriangles < mesh->maxtriangles)
7496 mesh->numtriangles++;
7498 element[1] = element[2];
7502 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7506 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7507 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7508 e = mesh->element3i + mesh->numtriangles * 3;
7509 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7511 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7512 if (mesh->numtriangles < mesh->maxtriangles)
7517 mesh->numtriangles++;
7519 element[1] = element[2];
7523 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7524 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7526 int planenum, planenum2;
7529 mplane_t *plane, *plane2;
7531 double temppoints[2][256*3];
7532 // figure out how large a bounding box we need to properly compute this brush
7534 for (w = 0;w < numplanes;w++)
7535 maxdist = max(maxdist, fabs(planes[w].dist));
7536 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7537 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7538 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7542 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7543 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7545 if (planenum2 == planenum)
7547 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);
7550 if (tempnumpoints < 3)
7552 // generate elements forming a triangle fan for this polygon
7553 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7557 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)
7559 texturelayer_t *layer;
7560 layer = t->currentlayers + t->currentnumlayers++;
7562 layer->depthmask = depthmask;
7563 layer->blendfunc1 = blendfunc1;
7564 layer->blendfunc2 = blendfunc2;
7565 layer->texture = texture;
7566 layer->texmatrix = *matrix;
7567 layer->color[0] = r;
7568 layer->color[1] = g;
7569 layer->color[2] = b;
7570 layer->color[3] = a;
7573 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7575 if(parms[0] == 0 && parms[1] == 0)
7577 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7578 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7583 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7586 index = parms[2] + rsurface.shadertime * parms[3];
7587 index -= floor(index);
7588 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7591 case Q3WAVEFUNC_NONE:
7592 case Q3WAVEFUNC_NOISE:
7593 case Q3WAVEFUNC_COUNT:
7596 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7597 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7598 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7599 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7600 case Q3WAVEFUNC_TRIANGLE:
7602 f = index - floor(index);
7615 f = parms[0] + parms[1] * f;
7616 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7617 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7621 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7627 matrix4x4_t matrix, temp;
7628 switch(tcmod->tcmod)
7632 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7633 matrix = r_waterscrollmatrix;
7635 matrix = identitymatrix;
7637 case Q3TCMOD_ENTITYTRANSLATE:
7638 // this is used in Q3 to allow the gamecode to control texcoord
7639 // scrolling on the entity, which is not supported in darkplaces yet.
7640 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7642 case Q3TCMOD_ROTATE:
7643 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7644 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7645 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7648 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7650 case Q3TCMOD_SCROLL:
7651 // extra care is needed because of precision breakdown with large values of time
7652 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7653 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7654 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7656 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7657 w = (int) tcmod->parms[0];
7658 h = (int) tcmod->parms[1];
7659 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7661 idx = (int) floor(f * w * h);
7662 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7664 case Q3TCMOD_STRETCH:
7665 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7666 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7668 case Q3TCMOD_TRANSFORM:
7669 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7670 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7671 VectorSet(tcmat + 6, 0 , 0 , 1);
7672 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7673 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7675 case Q3TCMOD_TURBULENT:
7676 // this is handled in the RSurf_PrepareVertices function
7677 matrix = identitymatrix;
7681 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7684 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7686 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7687 char name[MAX_QPATH];
7688 skinframe_t *skinframe;
7689 unsigned char pixels[296*194];
7690 strlcpy(cache->name, skinname, sizeof(cache->name));
7691 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7692 if (developer_loading.integer)
7693 Con_Printf("loading %s\n", name);
7694 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7695 if (!skinframe || !skinframe->base)
7698 fs_offset_t filesize;
7700 f = FS_LoadFile(name, tempmempool, true, &filesize);
7703 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7704 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7708 cache->skinframe = skinframe;
7711 texture_t *R_GetCurrentTexture(texture_t *t)
7714 const entity_render_t *ent = rsurface.entity;
7715 dp_model_t *model = ent->model;
7716 q3shaderinfo_layer_tcmod_t *tcmod;
7718 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7719 return t->currentframe;
7720 t->update_lastrenderframe = r_textureframe;
7721 t->update_lastrenderentity = (void *)ent;
7723 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7724 t->camera_entity = ent->entitynumber;
7726 t->camera_entity = 0;
7728 // switch to an alternate material if this is a q1bsp animated material
7730 texture_t *texture = t;
7731 int s = rsurface.ent_skinnum;
7732 if ((unsigned int)s >= (unsigned int)model->numskins)
7734 if (model->skinscenes)
7736 if (model->skinscenes[s].framecount > 1)
7737 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7739 s = model->skinscenes[s].firstframe;
7742 t = t + s * model->num_surfaces;
7745 // use an alternate animation if the entity's frame is not 0,
7746 // and only if the texture has an alternate animation
7747 if (rsurface.ent_alttextures && t->anim_total[1])
7748 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7750 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7752 texture->currentframe = t;
7755 // update currentskinframe to be a qw skin or animation frame
7756 if (rsurface.ent_qwskin >= 0)
7758 i = rsurface.ent_qwskin;
7759 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7761 r_qwskincache_size = cl.maxclients;
7763 Mem_Free(r_qwskincache);
7764 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7766 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7767 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7768 t->currentskinframe = r_qwskincache[i].skinframe;
7769 if (t->currentskinframe == NULL)
7770 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7772 else if (t->numskinframes >= 2)
7773 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7774 if (t->backgroundnumskinframes >= 2)
7775 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7777 t->currentmaterialflags = t->basematerialflags;
7778 t->currentalpha = rsurface.colormod[3];
7779 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7780 t->currentalpha *= r_wateralpha.value;
7781 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7782 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7783 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7784 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7785 if (!(rsurface.ent_flags & RENDER_LIGHT))
7786 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7787 else if (FAKELIGHT_ENABLED)
7789 // no modellight if using fakelight for the map
7791 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7793 // pick a model lighting mode
7794 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7795 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7797 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7799 if (rsurface.ent_flags & RENDER_ADDITIVE)
7800 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7801 else if (t->currentalpha < 1)
7802 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7803 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7804 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7805 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7806 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7807 if (t->backgroundnumskinframes)
7808 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7809 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7811 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7812 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7815 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7816 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7818 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7819 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7821 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7822 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7824 // there is no tcmod
7825 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7827 t->currenttexmatrix = r_waterscrollmatrix;
7828 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7830 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7832 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7833 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7836 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7837 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7838 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7839 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7841 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7842 if (t->currentskinframe->qpixels)
7843 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7844 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7845 if (!t->basetexture)
7846 t->basetexture = r_texture_notexture;
7847 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7848 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7849 t->nmaptexture = t->currentskinframe->nmap;
7850 if (!t->nmaptexture)
7851 t->nmaptexture = r_texture_blanknormalmap;
7852 t->glosstexture = r_texture_black;
7853 t->glowtexture = t->currentskinframe->glow;
7854 t->fogtexture = t->currentskinframe->fog;
7855 t->reflectmasktexture = t->currentskinframe->reflect;
7856 if (t->backgroundnumskinframes)
7858 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7859 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7860 t->backgroundglosstexture = r_texture_black;
7861 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7862 if (!t->backgroundnmaptexture)
7863 t->backgroundnmaptexture = r_texture_blanknormalmap;
7867 t->backgroundbasetexture = r_texture_white;
7868 t->backgroundnmaptexture = r_texture_blanknormalmap;
7869 t->backgroundglosstexture = r_texture_black;
7870 t->backgroundglowtexture = NULL;
7872 t->specularpower = r_shadow_glossexponent.value;
7873 // TODO: store reference values for these in the texture?
7874 t->specularscale = 0;
7875 if (r_shadow_gloss.integer > 0)
7877 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7879 if (r_shadow_glossintensity.value > 0)
7881 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7882 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7883 t->specularscale = r_shadow_glossintensity.value;
7886 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7888 t->glosstexture = r_texture_white;
7889 t->backgroundglosstexture = r_texture_white;
7890 t->specularscale = r_shadow_gloss2intensity.value;
7891 t->specularpower = r_shadow_gloss2exponent.value;
7894 t->specularscale *= t->specularscalemod;
7895 t->specularpower *= t->specularpowermod;
7897 // lightmaps mode looks bad with dlights using actual texturing, so turn
7898 // off the colormap and glossmap, but leave the normalmap on as it still
7899 // accurately represents the shading involved
7900 if (gl_lightmaps.integer)
7902 t->basetexture = r_texture_grey128;
7903 t->pantstexture = r_texture_black;
7904 t->shirttexture = r_texture_black;
7905 t->nmaptexture = r_texture_blanknormalmap;
7906 t->glosstexture = r_texture_black;
7907 t->glowtexture = NULL;
7908 t->fogtexture = NULL;
7909 t->reflectmasktexture = NULL;
7910 t->backgroundbasetexture = NULL;
7911 t->backgroundnmaptexture = r_texture_blanknormalmap;
7912 t->backgroundglosstexture = r_texture_black;
7913 t->backgroundglowtexture = NULL;
7914 t->specularscale = 0;
7915 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7918 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7919 VectorClear(t->dlightcolor);
7920 t->currentnumlayers = 0;
7921 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7923 int blendfunc1, blendfunc2;
7925 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7927 blendfunc1 = GL_SRC_ALPHA;
7928 blendfunc2 = GL_ONE;
7930 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7932 blendfunc1 = GL_SRC_ALPHA;
7933 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7935 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7937 blendfunc1 = t->customblendfunc[0];
7938 blendfunc2 = t->customblendfunc[1];
7942 blendfunc1 = GL_ONE;
7943 blendfunc2 = GL_ZERO;
7945 // don't colormod evilblend textures
7946 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7947 VectorSet(t->lightmapcolor, 1, 1, 1);
7948 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7949 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7951 // fullbright is not affected by r_refdef.lightmapintensity
7952 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]);
7953 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7954 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]);
7955 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7956 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]);
7960 vec3_t ambientcolor;
7962 // set the color tint used for lights affecting this surface
7963 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7965 // q3bsp has no lightmap updates, so the lightstylevalue that
7966 // would normally be baked into the lightmap must be
7967 // applied to the color
7968 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7969 if (model->type == mod_brushq3)
7970 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7971 colorscale *= r_refdef.lightmapintensity;
7972 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7973 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7974 // basic lit geometry
7975 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]);
7976 // add pants/shirt if needed
7977 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7978 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]);
7979 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7980 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]);
7981 // now add ambient passes if needed
7982 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7984 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]);
7985 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7986 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]);
7987 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7988 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]);
7991 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7992 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]);
7993 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7995 // if this is opaque use alpha blend which will darken the earlier
7998 // if this is an alpha blended material, all the earlier passes
7999 // were darkened by fog already, so we only need to add the fog
8000 // color ontop through the fog mask texture
8002 // if this is an additive blended material, all the earlier passes
8003 // were darkened by fog already, and we should not add fog color
8004 // (because the background was not darkened, there is no fog color
8005 // that was lost behind it).
8006 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]);
8010 return t->currentframe;
8013 rsurfacestate_t rsurface;
8015 void RSurf_ActiveWorldEntity(void)
8017 dp_model_t *model = r_refdef.scene.worldmodel;
8018 //if (rsurface.entity == r_refdef.scene.worldentity)
8020 rsurface.entity = r_refdef.scene.worldentity;
8021 rsurface.skeleton = NULL;
8022 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8023 rsurface.ent_skinnum = 0;
8024 rsurface.ent_qwskin = -1;
8025 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8026 rsurface.shadertime = r_refdef.scene.time;
8027 rsurface.matrix = identitymatrix;
8028 rsurface.inversematrix = identitymatrix;
8029 rsurface.matrixscale = 1;
8030 rsurface.inversematrixscale = 1;
8031 R_EntityMatrix(&identitymatrix);
8032 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8033 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8034 rsurface.fograngerecip = r_refdef.fograngerecip;
8035 rsurface.fogheightfade = r_refdef.fogheightfade;
8036 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8037 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8038 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8039 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8040 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8041 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8042 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8043 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8044 rsurface.colormod[3] = 1;
8045 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);
8046 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8047 rsurface.frameblend[0].lerp = 1;
8048 rsurface.ent_alttextures = false;
8049 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8050 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8051 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8052 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8053 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8054 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8055 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8056 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8057 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8058 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8059 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8060 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8061 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8062 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8063 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8064 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8065 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8066 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8067 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8068 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8069 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8070 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8071 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8072 rsurface.modelelement3i = model->surfmesh.data_element3i;
8073 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8074 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8075 rsurface.modelelement3s = model->surfmesh.data_element3s;
8076 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8077 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8078 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8079 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8080 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8081 rsurface.modelsurfaces = model->data_surfaces;
8082 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8083 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8084 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8085 rsurface.modelgeneratedvertex = false;
8086 rsurface.batchgeneratedvertex = false;
8087 rsurface.batchfirstvertex = 0;
8088 rsurface.batchnumvertices = 0;
8089 rsurface.batchfirsttriangle = 0;
8090 rsurface.batchnumtriangles = 0;
8091 rsurface.batchvertex3f = NULL;
8092 rsurface.batchvertex3f_vertexbuffer = NULL;
8093 rsurface.batchvertex3f_bufferoffset = 0;
8094 rsurface.batchsvector3f = NULL;
8095 rsurface.batchsvector3f_vertexbuffer = NULL;
8096 rsurface.batchsvector3f_bufferoffset = 0;
8097 rsurface.batchtvector3f = NULL;
8098 rsurface.batchtvector3f_vertexbuffer = NULL;
8099 rsurface.batchtvector3f_bufferoffset = 0;
8100 rsurface.batchnormal3f = NULL;
8101 rsurface.batchnormal3f_vertexbuffer = NULL;
8102 rsurface.batchnormal3f_bufferoffset = 0;
8103 rsurface.batchlightmapcolor4f = NULL;
8104 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8105 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8106 rsurface.batchtexcoordtexture2f = NULL;
8107 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8108 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8109 rsurface.batchtexcoordlightmap2f = NULL;
8110 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8111 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8112 rsurface.batchvertexmesh = NULL;
8113 rsurface.batchvertexmeshbuffer = NULL;
8114 rsurface.batchvertex3fbuffer = NULL;
8115 rsurface.batchelement3i = NULL;
8116 rsurface.batchelement3i_indexbuffer = NULL;
8117 rsurface.batchelement3i_bufferoffset = 0;
8118 rsurface.batchelement3s = NULL;
8119 rsurface.batchelement3s_indexbuffer = NULL;
8120 rsurface.batchelement3s_bufferoffset = 0;
8121 rsurface.passcolor4f = NULL;
8122 rsurface.passcolor4f_vertexbuffer = NULL;
8123 rsurface.passcolor4f_bufferoffset = 0;
8126 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8128 dp_model_t *model = ent->model;
8129 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8131 rsurface.entity = (entity_render_t *)ent;
8132 rsurface.skeleton = ent->skeleton;
8133 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8134 rsurface.ent_skinnum = ent->skinnum;
8135 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;
8136 rsurface.ent_flags = ent->flags;
8137 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8138 rsurface.matrix = ent->matrix;
8139 rsurface.inversematrix = ent->inversematrix;
8140 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8141 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8142 R_EntityMatrix(&rsurface.matrix);
8143 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8144 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8145 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8146 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8147 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8148 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8149 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8150 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8151 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8152 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8153 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8154 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8155 rsurface.colormod[3] = ent->alpha;
8156 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8157 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8158 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8159 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8160 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8161 if (ent->model->brush.submodel && !prepass)
8163 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8164 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8166 if (model->surfmesh.isanimated && model->AnimateVertices)
8168 if (ent->animcache_vertex3f)
8170 rsurface.modelvertex3f = ent->animcache_vertex3f;
8171 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8172 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8173 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8174 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8175 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8176 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8178 else if (wanttangents)
8180 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8181 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8182 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8183 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8184 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8185 rsurface.modelvertexmesh = NULL;
8186 rsurface.modelvertexmeshbuffer = NULL;
8187 rsurface.modelvertex3fbuffer = NULL;
8189 else if (wantnormals)
8191 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8192 rsurface.modelsvector3f = NULL;
8193 rsurface.modeltvector3f = NULL;
8194 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8195 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8196 rsurface.modelvertexmesh = NULL;
8197 rsurface.modelvertexmeshbuffer = NULL;
8198 rsurface.modelvertex3fbuffer = NULL;
8202 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8203 rsurface.modelsvector3f = NULL;
8204 rsurface.modeltvector3f = NULL;
8205 rsurface.modelnormal3f = NULL;
8206 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8207 rsurface.modelvertexmesh = NULL;
8208 rsurface.modelvertexmeshbuffer = NULL;
8209 rsurface.modelvertex3fbuffer = NULL;
8211 rsurface.modelvertex3f_vertexbuffer = 0;
8212 rsurface.modelvertex3f_bufferoffset = 0;
8213 rsurface.modelsvector3f_vertexbuffer = 0;
8214 rsurface.modelsvector3f_bufferoffset = 0;
8215 rsurface.modeltvector3f_vertexbuffer = 0;
8216 rsurface.modeltvector3f_bufferoffset = 0;
8217 rsurface.modelnormal3f_vertexbuffer = 0;
8218 rsurface.modelnormal3f_bufferoffset = 0;
8219 rsurface.modelgeneratedvertex = true;
8223 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8224 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8225 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8226 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8227 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8228 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8229 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8230 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8231 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8232 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8233 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8234 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8235 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8236 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8237 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8238 rsurface.modelgeneratedvertex = false;
8240 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8241 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8242 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8243 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8244 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8245 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8246 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8247 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8248 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8249 rsurface.modelelement3i = model->surfmesh.data_element3i;
8250 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8251 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8252 rsurface.modelelement3s = model->surfmesh.data_element3s;
8253 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8254 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8255 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8256 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8257 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8258 rsurface.modelsurfaces = model->data_surfaces;
8259 rsurface.batchgeneratedvertex = false;
8260 rsurface.batchfirstvertex = 0;
8261 rsurface.batchnumvertices = 0;
8262 rsurface.batchfirsttriangle = 0;
8263 rsurface.batchnumtriangles = 0;
8264 rsurface.batchvertex3f = NULL;
8265 rsurface.batchvertex3f_vertexbuffer = NULL;
8266 rsurface.batchvertex3f_bufferoffset = 0;
8267 rsurface.batchsvector3f = NULL;
8268 rsurface.batchsvector3f_vertexbuffer = NULL;
8269 rsurface.batchsvector3f_bufferoffset = 0;
8270 rsurface.batchtvector3f = NULL;
8271 rsurface.batchtvector3f_vertexbuffer = NULL;
8272 rsurface.batchtvector3f_bufferoffset = 0;
8273 rsurface.batchnormal3f = NULL;
8274 rsurface.batchnormal3f_vertexbuffer = NULL;
8275 rsurface.batchnormal3f_bufferoffset = 0;
8276 rsurface.batchlightmapcolor4f = NULL;
8277 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8278 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8279 rsurface.batchtexcoordtexture2f = NULL;
8280 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8281 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8282 rsurface.batchtexcoordlightmap2f = NULL;
8283 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8284 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8285 rsurface.batchvertexmesh = NULL;
8286 rsurface.batchvertexmeshbuffer = NULL;
8287 rsurface.batchvertex3fbuffer = NULL;
8288 rsurface.batchelement3i = NULL;
8289 rsurface.batchelement3i_indexbuffer = NULL;
8290 rsurface.batchelement3i_bufferoffset = 0;
8291 rsurface.batchelement3s = NULL;
8292 rsurface.batchelement3s_indexbuffer = NULL;
8293 rsurface.batchelement3s_bufferoffset = 0;
8294 rsurface.passcolor4f = NULL;
8295 rsurface.passcolor4f_vertexbuffer = NULL;
8296 rsurface.passcolor4f_bufferoffset = 0;
8299 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)
8301 rsurface.entity = r_refdef.scene.worldentity;
8302 rsurface.skeleton = NULL;
8303 rsurface.ent_skinnum = 0;
8304 rsurface.ent_qwskin = -1;
8305 rsurface.ent_flags = entflags;
8306 rsurface.shadertime = r_refdef.scene.time - shadertime;
8307 rsurface.modelnumvertices = numvertices;
8308 rsurface.modelnumtriangles = numtriangles;
8309 rsurface.matrix = *matrix;
8310 rsurface.inversematrix = *inversematrix;
8311 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8312 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8313 R_EntityMatrix(&rsurface.matrix);
8314 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8315 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8316 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8317 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8318 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8319 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8320 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8321 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8322 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8323 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8324 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8325 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8326 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);
8327 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8328 rsurface.frameblend[0].lerp = 1;
8329 rsurface.ent_alttextures = false;
8330 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8331 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8334 rsurface.modelvertex3f = (float *)vertex3f;
8335 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8336 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8337 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8339 else if (wantnormals)
8341 rsurface.modelvertex3f = (float *)vertex3f;
8342 rsurface.modelsvector3f = NULL;
8343 rsurface.modeltvector3f = NULL;
8344 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8348 rsurface.modelvertex3f = (float *)vertex3f;
8349 rsurface.modelsvector3f = NULL;
8350 rsurface.modeltvector3f = NULL;
8351 rsurface.modelnormal3f = NULL;
8353 rsurface.modelvertexmesh = NULL;
8354 rsurface.modelvertexmeshbuffer = NULL;
8355 rsurface.modelvertex3fbuffer = NULL;
8356 rsurface.modelvertex3f_vertexbuffer = 0;
8357 rsurface.modelvertex3f_bufferoffset = 0;
8358 rsurface.modelsvector3f_vertexbuffer = 0;
8359 rsurface.modelsvector3f_bufferoffset = 0;
8360 rsurface.modeltvector3f_vertexbuffer = 0;
8361 rsurface.modeltvector3f_bufferoffset = 0;
8362 rsurface.modelnormal3f_vertexbuffer = 0;
8363 rsurface.modelnormal3f_bufferoffset = 0;
8364 rsurface.modelgeneratedvertex = true;
8365 rsurface.modellightmapcolor4f = (float *)color4f;
8366 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8367 rsurface.modellightmapcolor4f_bufferoffset = 0;
8368 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8369 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8370 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8371 rsurface.modeltexcoordlightmap2f = NULL;
8372 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8373 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8374 rsurface.modelelement3i = (int *)element3i;
8375 rsurface.modelelement3i_indexbuffer = NULL;
8376 rsurface.modelelement3i_bufferoffset = 0;
8377 rsurface.modelelement3s = (unsigned short *)element3s;
8378 rsurface.modelelement3s_indexbuffer = NULL;
8379 rsurface.modelelement3s_bufferoffset = 0;
8380 rsurface.modellightmapoffsets = NULL;
8381 rsurface.modelsurfaces = NULL;
8382 rsurface.batchgeneratedvertex = false;
8383 rsurface.batchfirstvertex = 0;
8384 rsurface.batchnumvertices = 0;
8385 rsurface.batchfirsttriangle = 0;
8386 rsurface.batchnumtriangles = 0;
8387 rsurface.batchvertex3f = NULL;
8388 rsurface.batchvertex3f_vertexbuffer = NULL;
8389 rsurface.batchvertex3f_bufferoffset = 0;
8390 rsurface.batchsvector3f = NULL;
8391 rsurface.batchsvector3f_vertexbuffer = NULL;
8392 rsurface.batchsvector3f_bufferoffset = 0;
8393 rsurface.batchtvector3f = NULL;
8394 rsurface.batchtvector3f_vertexbuffer = NULL;
8395 rsurface.batchtvector3f_bufferoffset = 0;
8396 rsurface.batchnormal3f = NULL;
8397 rsurface.batchnormal3f_vertexbuffer = NULL;
8398 rsurface.batchnormal3f_bufferoffset = 0;
8399 rsurface.batchlightmapcolor4f = NULL;
8400 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8401 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8402 rsurface.batchtexcoordtexture2f = NULL;
8403 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8404 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8405 rsurface.batchtexcoordlightmap2f = NULL;
8406 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8407 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8408 rsurface.batchvertexmesh = NULL;
8409 rsurface.batchvertexmeshbuffer = NULL;
8410 rsurface.batchvertex3fbuffer = NULL;
8411 rsurface.batchelement3i = NULL;
8412 rsurface.batchelement3i_indexbuffer = NULL;
8413 rsurface.batchelement3i_bufferoffset = 0;
8414 rsurface.batchelement3s = NULL;
8415 rsurface.batchelement3s_indexbuffer = NULL;
8416 rsurface.batchelement3s_bufferoffset = 0;
8417 rsurface.passcolor4f = NULL;
8418 rsurface.passcolor4f_vertexbuffer = NULL;
8419 rsurface.passcolor4f_bufferoffset = 0;
8421 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8423 if ((wantnormals || wanttangents) && !normal3f)
8425 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8426 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8428 if (wanttangents && !svector3f)
8430 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8431 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8432 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8437 float RSurf_FogPoint(const float *v)
8439 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8440 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8441 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8442 float FogHeightFade = r_refdef.fogheightfade;
8444 unsigned int fogmasktableindex;
8445 if (r_refdef.fogplaneviewabove)
8446 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8448 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8449 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8450 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8453 float RSurf_FogVertex(const float *v)
8455 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8456 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8457 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8458 float FogHeightFade = rsurface.fogheightfade;
8460 unsigned int fogmasktableindex;
8461 if (r_refdef.fogplaneviewabove)
8462 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8464 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8465 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8466 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8469 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8472 for (i = 0;i < numelements;i++)
8473 outelement3i[i] = inelement3i[i] + adjust;
8476 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8477 extern cvar_t gl_vbo;
8478 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8486 int surfacefirsttriangle;
8487 int surfacenumtriangles;
8488 int surfacefirstvertex;
8489 int surfaceendvertex;
8490 int surfacenumvertices;
8491 int batchnumvertices;
8492 int batchnumtriangles;
8496 qboolean dynamicvertex;
8500 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8502 q3shaderinfo_deform_t *deform;
8503 const msurface_t *surface, *firstsurface;
8504 r_vertexmesh_t *vertexmesh;
8505 if (!texturenumsurfaces)
8507 // find vertex range of this surface batch
8509 firstsurface = texturesurfacelist[0];
8510 firsttriangle = firstsurface->num_firsttriangle;
8511 batchnumvertices = 0;
8512 batchnumtriangles = 0;
8513 firstvertex = endvertex = firstsurface->num_firstvertex;
8514 for (i = 0;i < texturenumsurfaces;i++)
8516 surface = texturesurfacelist[i];
8517 if (surface != firstsurface + i)
8519 surfacefirstvertex = surface->num_firstvertex;
8520 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8521 surfacenumvertices = surface->num_vertices;
8522 surfacenumtriangles = surface->num_triangles;
8523 if (firstvertex > surfacefirstvertex)
8524 firstvertex = surfacefirstvertex;
8525 if (endvertex < surfaceendvertex)
8526 endvertex = surfaceendvertex;
8527 batchnumvertices += surfacenumvertices;
8528 batchnumtriangles += surfacenumtriangles;
8531 // we now know the vertex range used, and if there are any gaps in it
8532 rsurface.batchfirstvertex = firstvertex;
8533 rsurface.batchnumvertices = endvertex - firstvertex;
8534 rsurface.batchfirsttriangle = firsttriangle;
8535 rsurface.batchnumtriangles = batchnumtriangles;
8537 // this variable holds flags for which properties have been updated that
8538 // may require regenerating vertexmesh array...
8541 // check if any dynamic vertex processing must occur
8542 dynamicvertex = false;
8544 // if there is a chance of animated vertex colors, it's a dynamic batch
8545 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8547 dynamicvertex = true;
8548 batchneed |= BATCHNEED_NOGAPS;
8549 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8552 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8554 switch (deform->deform)
8557 case Q3DEFORM_PROJECTIONSHADOW:
8558 case Q3DEFORM_TEXT0:
8559 case Q3DEFORM_TEXT1:
8560 case Q3DEFORM_TEXT2:
8561 case Q3DEFORM_TEXT3:
8562 case Q3DEFORM_TEXT4:
8563 case Q3DEFORM_TEXT5:
8564 case Q3DEFORM_TEXT6:
8565 case Q3DEFORM_TEXT7:
8568 case Q3DEFORM_AUTOSPRITE:
8569 dynamicvertex = true;
8570 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8571 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8573 case Q3DEFORM_AUTOSPRITE2:
8574 dynamicvertex = true;
8575 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8576 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8578 case Q3DEFORM_NORMAL:
8579 dynamicvertex = true;
8580 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8581 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8584 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8585 break; // if wavefunc is a nop, ignore this transform
8586 dynamicvertex = true;
8587 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8588 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8590 case Q3DEFORM_BULGE:
8591 dynamicvertex = true;
8592 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8593 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8596 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8597 break; // if wavefunc is a nop, ignore this transform
8598 dynamicvertex = true;
8599 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8600 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8604 switch(rsurface.texture->tcgen.tcgen)
8607 case Q3TCGEN_TEXTURE:
8609 case Q3TCGEN_LIGHTMAP:
8610 dynamicvertex = true;
8611 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8612 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8614 case Q3TCGEN_VECTOR:
8615 dynamicvertex = true;
8616 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8617 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8619 case Q3TCGEN_ENVIRONMENT:
8620 dynamicvertex = true;
8621 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8622 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8625 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8627 dynamicvertex = true;
8628 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8629 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8632 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8634 dynamicvertex = true;
8635 batchneed |= BATCHNEED_NOGAPS;
8636 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8639 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8641 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8642 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8643 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8644 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8645 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8646 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8647 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8650 // when the model data has no vertex buffer (dynamic mesh), we need to
8652 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8653 batchneed |= BATCHNEED_NOGAPS;
8655 // if needsupdate, we have to do a dynamic vertex batch for sure
8656 if (needsupdate & batchneed)
8657 dynamicvertex = true;
8659 // see if we need to build vertexmesh from arrays
8660 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8661 dynamicvertex = true;
8663 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8664 // also some drivers strongly dislike firstvertex
8665 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8666 dynamicvertex = true;
8668 rsurface.batchvertex3f = rsurface.modelvertex3f;
8669 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8670 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8671 rsurface.batchsvector3f = rsurface.modelsvector3f;
8672 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8673 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8674 rsurface.batchtvector3f = rsurface.modeltvector3f;
8675 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8676 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8677 rsurface.batchnormal3f = rsurface.modelnormal3f;
8678 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8679 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8680 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8681 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8682 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8683 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8684 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8685 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8686 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8687 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8688 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8689 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8690 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8691 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8692 rsurface.batchelement3i = rsurface.modelelement3i;
8693 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8694 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8695 rsurface.batchelement3s = rsurface.modelelement3s;
8696 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8697 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8699 // if any dynamic vertex processing has to occur in software, we copy the
8700 // entire surface list together before processing to rebase the vertices
8701 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8703 // if any gaps exist and we do not have a static vertex buffer, we have to
8704 // copy the surface list together to avoid wasting upload bandwidth on the
8705 // vertices in the gaps.
8707 // if gaps exist and we have a static vertex buffer, we still have to
8708 // combine the index buffer ranges into one dynamic index buffer.
8710 // in all cases we end up with data that can be drawn in one call.
8714 // static vertex data, just set pointers...
8715 rsurface.batchgeneratedvertex = false;
8716 // if there are gaps, we want to build a combined index buffer,
8717 // otherwise use the original static buffer with an appropriate offset
8720 // build a new triangle elements array for this batch
8721 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8722 rsurface.batchfirsttriangle = 0;
8724 for (i = 0;i < texturenumsurfaces;i++)
8726 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8727 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8728 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8729 numtriangles += surfacenumtriangles;
8731 rsurface.batchelement3i_indexbuffer = NULL;
8732 rsurface.batchelement3i_bufferoffset = 0;
8733 rsurface.batchelement3s = NULL;
8734 rsurface.batchelement3s_indexbuffer = NULL;
8735 rsurface.batchelement3s_bufferoffset = 0;
8736 if (endvertex <= 65536)
8738 // make a 16bit (unsigned short) index array if possible
8739 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8740 for (i = 0;i < numtriangles*3;i++)
8741 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8747 // something needs software processing, do it for real...
8748 // we only directly handle separate array data in this case and then
8749 // generate interleaved data if needed...
8750 rsurface.batchgeneratedvertex = true;
8752 // now copy the vertex data into a combined array and make an index array
8753 // (this is what Quake3 does all the time)
8754 //if (gaps || rsurface.batchfirstvertex)
8756 rsurface.batchvertex3fbuffer = NULL;
8757 rsurface.batchvertexmesh = NULL;
8758 rsurface.batchvertexmeshbuffer = NULL;
8759 rsurface.batchvertex3f = NULL;
8760 rsurface.batchvertex3f_vertexbuffer = NULL;
8761 rsurface.batchvertex3f_bufferoffset = 0;
8762 rsurface.batchsvector3f = NULL;
8763 rsurface.batchsvector3f_vertexbuffer = NULL;
8764 rsurface.batchsvector3f_bufferoffset = 0;
8765 rsurface.batchtvector3f = NULL;
8766 rsurface.batchtvector3f_vertexbuffer = NULL;
8767 rsurface.batchtvector3f_bufferoffset = 0;
8768 rsurface.batchnormal3f = NULL;
8769 rsurface.batchnormal3f_vertexbuffer = NULL;
8770 rsurface.batchnormal3f_bufferoffset = 0;
8771 rsurface.batchlightmapcolor4f = NULL;
8772 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8773 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8774 rsurface.batchtexcoordtexture2f = NULL;
8775 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8776 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8777 rsurface.batchtexcoordlightmap2f = NULL;
8778 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8779 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8780 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8781 rsurface.batchelement3i_indexbuffer = NULL;
8782 rsurface.batchelement3i_bufferoffset = 0;
8783 rsurface.batchelement3s = NULL;
8784 rsurface.batchelement3s_indexbuffer = NULL;
8785 rsurface.batchelement3s_bufferoffset = 0;
8786 // we'll only be setting up certain arrays as needed
8787 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8788 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8789 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8790 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8791 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8792 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8793 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8795 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8796 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8799 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8800 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8801 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8802 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8803 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8806 for (i = 0;i < texturenumsurfaces;i++)
8808 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8809 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8810 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8811 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8812 // copy only the data requested
8813 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8814 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8815 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8817 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8819 if (rsurface.batchvertex3f)
8820 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8822 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8824 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8826 if (rsurface.modelnormal3f)
8827 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8829 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8831 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8833 if (rsurface.modelsvector3f)
8835 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8836 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8840 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8841 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8844 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8846 if (rsurface.modellightmapcolor4f)
8847 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8849 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8851 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8853 if (rsurface.modeltexcoordtexture2f)
8854 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8856 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8858 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8860 if (rsurface.modeltexcoordlightmap2f)
8861 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8863 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8866 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8867 numvertices += surfacenumvertices;
8868 numtriangles += surfacenumtriangles;
8871 // generate a 16bit index array as well if possible
8872 // (in general, dynamic batches fit)
8873 if (numvertices <= 65536)
8875 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8876 for (i = 0;i < numtriangles*3;i++)
8877 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8880 // since we've copied everything, the batch now starts at 0
8881 rsurface.batchfirstvertex = 0;
8882 rsurface.batchnumvertices = batchnumvertices;
8883 rsurface.batchfirsttriangle = 0;
8884 rsurface.batchnumtriangles = batchnumtriangles;
8887 // q1bsp surfaces rendered in vertex color mode have to have colors
8888 // calculated based on lightstyles
8889 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8891 // generate color arrays for the surfaces in this list
8896 const unsigned char *lm;
8897 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8898 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8899 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8901 for (i = 0;i < texturenumsurfaces;i++)
8903 surface = texturesurfacelist[i];
8904 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8905 surfacenumvertices = surface->num_vertices;
8906 if (surface->lightmapinfo->samples)
8908 for (j = 0;j < surfacenumvertices;j++)
8910 lm = surface->lightmapinfo->samples + offsets[j];
8911 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8912 VectorScale(lm, scale, c);
8913 if (surface->lightmapinfo->styles[1] != 255)
8915 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8917 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8918 VectorMA(c, scale, lm, c);
8919 if (surface->lightmapinfo->styles[2] != 255)
8922 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8923 VectorMA(c, scale, lm, c);
8924 if (surface->lightmapinfo->styles[3] != 255)
8927 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8928 VectorMA(c, scale, lm, c);
8935 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);
8941 for (j = 0;j < surfacenumvertices;j++)
8943 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8950 // if vertices are deformed (sprite flares and things in maps, possibly
8951 // water waves, bulges and other deformations), modify the copied vertices
8953 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8955 switch (deform->deform)
8958 case Q3DEFORM_PROJECTIONSHADOW:
8959 case Q3DEFORM_TEXT0:
8960 case Q3DEFORM_TEXT1:
8961 case Q3DEFORM_TEXT2:
8962 case Q3DEFORM_TEXT3:
8963 case Q3DEFORM_TEXT4:
8964 case Q3DEFORM_TEXT5:
8965 case Q3DEFORM_TEXT6:
8966 case Q3DEFORM_TEXT7:
8969 case Q3DEFORM_AUTOSPRITE:
8970 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8971 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8972 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8973 VectorNormalize(newforward);
8974 VectorNormalize(newright);
8975 VectorNormalize(newup);
8976 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8977 // rsurface.batchvertex3f_vertexbuffer = NULL;
8978 // rsurface.batchvertex3f_bufferoffset = 0;
8979 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8980 // rsurface.batchsvector3f_vertexbuffer = NULL;
8981 // rsurface.batchsvector3f_bufferoffset = 0;
8982 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8983 // rsurface.batchtvector3f_vertexbuffer = NULL;
8984 // rsurface.batchtvector3f_bufferoffset = 0;
8985 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8986 // rsurface.batchnormal3f_vertexbuffer = NULL;
8987 // rsurface.batchnormal3f_bufferoffset = 0;
8988 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8989 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8990 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8991 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8992 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);
8993 // a single autosprite surface can contain multiple sprites...
8994 for (j = 0;j < batchnumvertices - 3;j += 4)
8996 VectorClear(center);
8997 for (i = 0;i < 4;i++)
8998 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8999 VectorScale(center, 0.25f, center);
9000 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9001 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9002 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9003 for (i = 0;i < 4;i++)
9005 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9006 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9009 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9010 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9011 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);
9013 case Q3DEFORM_AUTOSPRITE2:
9014 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9015 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9016 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9017 VectorNormalize(newforward);
9018 VectorNormalize(newright);
9019 VectorNormalize(newup);
9020 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9021 // rsurface.batchvertex3f_vertexbuffer = NULL;
9022 // rsurface.batchvertex3f_bufferoffset = 0;
9024 const float *v1, *v2;
9034 memset(shortest, 0, sizeof(shortest));
9035 // a single autosprite surface can contain multiple sprites...
9036 for (j = 0;j < batchnumvertices - 3;j += 4)
9038 VectorClear(center);
9039 for (i = 0;i < 4;i++)
9040 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9041 VectorScale(center, 0.25f, center);
9042 // find the two shortest edges, then use them to define the
9043 // axis vectors for rotating around the central axis
9044 for (i = 0;i < 6;i++)
9046 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9047 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9048 l = VectorDistance2(v1, v2);
9049 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9051 l += (1.0f / 1024.0f);
9052 if (shortest[0].length2 > l || i == 0)
9054 shortest[1] = shortest[0];
9055 shortest[0].length2 = l;
9056 shortest[0].v1 = v1;
9057 shortest[0].v2 = v2;
9059 else if (shortest[1].length2 > l || i == 1)
9061 shortest[1].length2 = l;
9062 shortest[1].v1 = v1;
9063 shortest[1].v2 = v2;
9066 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9067 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9068 // this calculates the right vector from the shortest edge
9069 // and the up vector from the edge midpoints
9070 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9071 VectorNormalize(right);
9072 VectorSubtract(end, start, up);
9073 VectorNormalize(up);
9074 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9075 VectorSubtract(rsurface.localvieworigin, center, forward);
9076 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9077 VectorNegate(forward, forward);
9078 VectorReflect(forward, 0, up, forward);
9079 VectorNormalize(forward);
9080 CrossProduct(up, forward, newright);
9081 VectorNormalize(newright);
9082 // rotate the quad around the up axis vector, this is made
9083 // especially easy by the fact we know the quad is flat,
9084 // so we only have to subtract the center position and
9085 // measure distance along the right vector, and then
9086 // multiply that by the newright vector and add back the
9088 // we also need to subtract the old position to undo the
9089 // displacement from the center, which we do with a
9090 // DotProduct, the subtraction/addition of center is also
9091 // optimized into DotProducts here
9092 l = DotProduct(right, center);
9093 for (i = 0;i < 4;i++)
9095 v1 = rsurface.batchvertex3f + 3*(j+i);
9096 f = DotProduct(right, v1) - l;
9097 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9101 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9103 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9104 // rsurface.batchnormal3f_vertexbuffer = NULL;
9105 // rsurface.batchnormal3f_bufferoffset = 0;
9106 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9108 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9110 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9111 // rsurface.batchsvector3f_vertexbuffer = NULL;
9112 // rsurface.batchsvector3f_bufferoffset = 0;
9113 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9114 // rsurface.batchtvector3f_vertexbuffer = NULL;
9115 // rsurface.batchtvector3f_bufferoffset = 0;
9116 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);
9119 case Q3DEFORM_NORMAL:
9120 // deform the normals to make reflections wavey
9121 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9122 rsurface.batchnormal3f_vertexbuffer = NULL;
9123 rsurface.batchnormal3f_bufferoffset = 0;
9124 for (j = 0;j < batchnumvertices;j++)
9127 float *normal = rsurface.batchnormal3f + 3*j;
9128 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9129 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9130 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9131 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9132 VectorNormalize(normal);
9134 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9136 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9137 // rsurface.batchsvector3f_vertexbuffer = NULL;
9138 // rsurface.batchsvector3f_bufferoffset = 0;
9139 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9140 // rsurface.batchtvector3f_vertexbuffer = NULL;
9141 // rsurface.batchtvector3f_bufferoffset = 0;
9142 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);
9146 // deform vertex array to make wavey water and flags and such
9147 waveparms[0] = deform->waveparms[0];
9148 waveparms[1] = deform->waveparms[1];
9149 waveparms[2] = deform->waveparms[2];
9150 waveparms[3] = deform->waveparms[3];
9151 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9152 break; // if wavefunc is a nop, don't make a dynamic vertex array
9153 // this is how a divisor of vertex influence on deformation
9154 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9155 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9156 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9157 // rsurface.batchvertex3f_vertexbuffer = NULL;
9158 // rsurface.batchvertex3f_bufferoffset = 0;
9159 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9160 // rsurface.batchnormal3f_vertexbuffer = NULL;
9161 // rsurface.batchnormal3f_bufferoffset = 0;
9162 for (j = 0;j < batchnumvertices;j++)
9164 // if the wavefunc depends on time, evaluate it per-vertex
9167 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9168 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9170 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9172 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9173 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9174 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9176 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9177 // rsurface.batchsvector3f_vertexbuffer = NULL;
9178 // rsurface.batchsvector3f_bufferoffset = 0;
9179 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9180 // rsurface.batchtvector3f_vertexbuffer = NULL;
9181 // rsurface.batchtvector3f_bufferoffset = 0;
9182 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);
9185 case Q3DEFORM_BULGE:
9186 // deform vertex array to make the surface have moving bulges
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 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9196 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9198 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9199 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9200 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9202 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9203 // rsurface.batchsvector3f_vertexbuffer = NULL;
9204 // rsurface.batchsvector3f_bufferoffset = 0;
9205 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9206 // rsurface.batchtvector3f_vertexbuffer = NULL;
9207 // rsurface.batchtvector3f_bufferoffset = 0;
9208 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);
9212 // deform vertex array
9213 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9214 break; // if wavefunc is a nop, don't make a dynamic vertex array
9215 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9216 VectorScale(deform->parms, scale, waveparms);
9217 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9218 // rsurface.batchvertex3f_vertexbuffer = NULL;
9219 // rsurface.batchvertex3f_bufferoffset = 0;
9220 for (j = 0;j < batchnumvertices;j++)
9221 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9226 // generate texcoords based on the chosen texcoord source
9227 switch(rsurface.texture->tcgen.tcgen)
9230 case Q3TCGEN_TEXTURE:
9232 case Q3TCGEN_LIGHTMAP:
9233 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9234 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9235 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9236 if (rsurface.batchtexcoordlightmap2f)
9237 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9239 case Q3TCGEN_VECTOR:
9240 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9241 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9242 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9243 for (j = 0;j < batchnumvertices;j++)
9245 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9246 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9249 case Q3TCGEN_ENVIRONMENT:
9250 // make environment reflections using a spheremap
9251 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9252 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9253 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9254 for (j = 0;j < batchnumvertices;j++)
9256 // identical to Q3A's method, but executed in worldspace so
9257 // carried models can be shiny too
9259 float viewer[3], d, reflected[3], worldreflected[3];
9261 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9262 // VectorNormalize(viewer);
9264 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9266 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9267 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9268 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9269 // note: this is proportinal to viewer, so we can normalize later
9271 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9272 VectorNormalize(worldreflected);
9274 // note: this sphere map only uses world x and z!
9275 // so positive and negative y will LOOK THE SAME.
9276 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9277 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9281 // the only tcmod that needs software vertex processing is turbulent, so
9282 // check for it here and apply the changes if needed
9283 // and we only support that as the first one
9284 // (handling a mixture of turbulent and other tcmods would be problematic
9285 // without punting it entirely to a software path)
9286 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9288 amplitude = rsurface.texture->tcmods[0].parms[1];
9289 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9290 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9291 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9292 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9293 for (j = 0;j < batchnumvertices;j++)
9295 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);
9296 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9300 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9302 // convert the modified arrays to vertex structs
9303 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9304 // rsurface.batchvertexmeshbuffer = NULL;
9305 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9306 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9307 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9308 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9309 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9310 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9311 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9313 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9315 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9316 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9319 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9320 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9321 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9322 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9323 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9324 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9325 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9326 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9327 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9331 void RSurf_DrawBatch(void)
9333 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9334 // through the pipeline, killing it earlier in the pipeline would have
9335 // per-surface overhead rather than per-batch overhead, so it's best to
9336 // reject it here, before it hits glDraw.
9337 if (rsurface.batchnumtriangles == 0)
9340 // batch debugging code
9341 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9347 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9348 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9351 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9353 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9355 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9356 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);
9363 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);
9366 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9368 // pick the closest matching water plane
9369 int planeindex, vertexindex, bestplaneindex = -1;
9373 r_waterstate_waterplane_t *p;
9374 qboolean prepared = false;
9376 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9378 if(p->camera_entity != rsurface.texture->camera_entity)
9383 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9385 if(rsurface.batchnumvertices == 0)
9388 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9390 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9391 d += fabs(PlaneDiff(vert, &p->plane));
9393 if (bestd > d || bestplaneindex < 0)
9396 bestplaneindex = planeindex;
9399 return bestplaneindex;
9400 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9401 // this situation though, as it might be better to render single larger
9402 // batches with useless stuff (backface culled for example) than to
9403 // render multiple smaller batches
9406 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9409 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9410 rsurface.passcolor4f_vertexbuffer = 0;
9411 rsurface.passcolor4f_bufferoffset = 0;
9412 for (i = 0;i < rsurface.batchnumvertices;i++)
9413 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9416 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9423 if (rsurface.passcolor4f)
9425 // generate color arrays
9426 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9427 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9428 rsurface.passcolor4f_vertexbuffer = 0;
9429 rsurface.passcolor4f_bufferoffset = 0;
9430 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)
9432 f = RSurf_FogVertex(v);
9441 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9442 rsurface.passcolor4f_vertexbuffer = 0;
9443 rsurface.passcolor4f_bufferoffset = 0;
9444 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9446 f = RSurf_FogVertex(v);
9455 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9462 if (!rsurface.passcolor4f)
9464 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9465 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9466 rsurface.passcolor4f_vertexbuffer = 0;
9467 rsurface.passcolor4f_bufferoffset = 0;
9468 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9470 f = RSurf_FogVertex(v);
9471 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9472 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9473 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9478 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9483 if (!rsurface.passcolor4f)
9485 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9486 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9487 rsurface.passcolor4f_vertexbuffer = 0;
9488 rsurface.passcolor4f_bufferoffset = 0;
9489 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9498 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9503 if (!rsurface.passcolor4f)
9505 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9506 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9507 rsurface.passcolor4f_vertexbuffer = 0;
9508 rsurface.passcolor4f_bufferoffset = 0;
9509 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9511 c2[0] = c[0] + r_refdef.scene.ambient;
9512 c2[1] = c[1] + r_refdef.scene.ambient;
9513 c2[2] = c[2] + r_refdef.scene.ambient;
9518 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9521 rsurface.passcolor4f = NULL;
9522 rsurface.passcolor4f_vertexbuffer = 0;
9523 rsurface.passcolor4f_bufferoffset = 0;
9524 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9525 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9526 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9527 GL_Color(r, g, b, a);
9528 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9532 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9534 // TODO: optimize applyfog && applycolor case
9535 // just apply fog if necessary, and tint the fog color array if necessary
9536 rsurface.passcolor4f = NULL;
9537 rsurface.passcolor4f_vertexbuffer = 0;
9538 rsurface.passcolor4f_bufferoffset = 0;
9539 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9540 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9541 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9542 GL_Color(r, g, b, a);
9546 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9549 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9550 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9551 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9552 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9553 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9554 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9555 GL_Color(r, g, b, a);
9559 static void RSurf_DrawBatch_GL11_ClampColor(void)
9564 if (!rsurface.passcolor4f)
9566 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9568 c2[0] = bound(0.0f, c1[0], 1.0f);
9569 c2[1] = bound(0.0f, c1[1], 1.0f);
9570 c2[2] = bound(0.0f, c1[2], 1.0f);
9571 c2[3] = bound(0.0f, c1[3], 1.0f);
9575 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9585 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9586 rsurface.passcolor4f_vertexbuffer = 0;
9587 rsurface.passcolor4f_bufferoffset = 0;
9588 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)
9590 f = -DotProduct(r_refdef.view.forward, n);
9592 f = f * 0.85 + 0.15; // work around so stuff won't get black
9593 f *= r_refdef.lightmapintensity;
9594 Vector4Set(c, f, f, f, 1);
9598 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9600 RSurf_DrawBatch_GL11_ApplyFakeLight();
9601 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9602 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9603 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9604 GL_Color(r, g, b, a);
9608 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9616 vec3_t ambientcolor;
9617 vec3_t diffusecolor;
9621 VectorCopy(rsurface.modellight_lightdir, lightdir);
9622 f = 0.5f * r_refdef.lightmapintensity;
9623 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9624 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9625 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9626 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9627 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9628 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9630 if (VectorLength2(diffusecolor) > 0)
9632 // q3-style directional shading
9633 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9634 rsurface.passcolor4f_vertexbuffer = 0;
9635 rsurface.passcolor4f_bufferoffset = 0;
9636 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)
9638 if ((f = DotProduct(n, lightdir)) > 0)
9639 VectorMA(ambientcolor, f, diffusecolor, c);
9641 VectorCopy(ambientcolor, c);
9648 *applycolor = false;
9652 *r = ambientcolor[0];
9653 *g = ambientcolor[1];
9654 *b = ambientcolor[2];
9655 rsurface.passcolor4f = NULL;
9656 rsurface.passcolor4f_vertexbuffer = 0;
9657 rsurface.passcolor4f_bufferoffset = 0;
9661 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9663 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9664 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9665 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9666 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9667 GL_Color(r, g, b, a);
9671 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9679 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9680 rsurface.passcolor4f_vertexbuffer = 0;
9681 rsurface.passcolor4f_bufferoffset = 0;
9683 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9685 f = 1 - RSurf_FogVertex(v);
9693 void RSurf_SetupDepthAndCulling(void)
9695 // submodels are biased to avoid z-fighting with world surfaces that they
9696 // may be exactly overlapping (avoids z-fighting artifacts on certain
9697 // doors and things in Quake maps)
9698 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9699 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9700 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9701 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9704 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9706 // transparent sky would be ridiculous
9707 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9709 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9710 skyrenderlater = true;
9711 RSurf_SetupDepthAndCulling();
9713 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9714 // skymasking on them, and Quake3 never did sky masking (unlike
9715 // software Quake and software Quake2), so disable the sky masking
9716 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9717 // and skymasking also looks very bad when noclipping outside the
9718 // level, so don't use it then either.
9719 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9721 R_Mesh_ResetTextureState();
9722 if (skyrendermasked)
9724 R_SetupShader_DepthOrShadow(false);
9725 // depth-only (masking)
9726 GL_ColorMask(0,0,0,0);
9727 // just to make sure that braindead drivers don't draw
9728 // anything despite that colormask...
9729 GL_BlendFunc(GL_ZERO, GL_ONE);
9730 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9731 if (rsurface.batchvertex3fbuffer)
9732 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9734 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9738 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9740 GL_BlendFunc(GL_ONE, GL_ZERO);
9741 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9742 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9743 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9746 if (skyrendermasked)
9747 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9749 R_Mesh_ResetTextureState();
9750 GL_Color(1, 1, 1, 1);
9753 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9754 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9755 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9757 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9761 // render screenspace normalmap to texture
9763 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9767 // bind lightmap texture
9769 // water/refraction/reflection/camera surfaces have to be handled specially
9770 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9772 int start, end, startplaneindex;
9773 for (start = 0;start < texturenumsurfaces;start = end)
9775 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9776 if(startplaneindex < 0)
9778 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9779 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9783 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9785 // now that we have a batch using the same planeindex, render it
9786 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9788 // render water or distortion background
9790 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);
9792 // blend surface on top
9793 GL_DepthMask(false);
9794 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9797 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9799 // render surface with reflection texture as input
9800 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9801 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);
9808 // render surface batch normally
9809 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9810 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);
9814 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9816 // OpenGL 1.3 path - anything not completely ancient
9817 qboolean applycolor;
9820 const texturelayer_t *layer;
9821 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);
9822 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9824 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9827 int layertexrgbscale;
9828 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9830 if (layerindex == 0)
9834 GL_AlphaTest(false);
9835 GL_DepthFunc(GL_EQUAL);
9838 GL_DepthMask(layer->depthmask && writedepth);
9839 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9840 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9842 layertexrgbscale = 4;
9843 VectorScale(layer->color, 0.25f, layercolor);
9845 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9847 layertexrgbscale = 2;
9848 VectorScale(layer->color, 0.5f, layercolor);
9852 layertexrgbscale = 1;
9853 VectorScale(layer->color, 1.0f, layercolor);
9855 layercolor[3] = layer->color[3];
9856 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9857 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9858 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9859 switch (layer->type)
9861 case TEXTURELAYERTYPE_LITTEXTURE:
9862 // single-pass lightmapped texture with 2x rgbscale
9863 R_Mesh_TexBind(0, r_texture_white);
9864 R_Mesh_TexMatrix(0, NULL);
9865 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9866 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9867 R_Mesh_TexBind(1, layer->texture);
9868 R_Mesh_TexMatrix(1, &layer->texmatrix);
9869 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9870 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9871 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9872 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9873 else if (FAKELIGHT_ENABLED)
9874 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9875 else if (rsurface.uselightmaptexture)
9876 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9878 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9880 case TEXTURELAYERTYPE_TEXTURE:
9881 // singletexture unlit texture with transparency support
9882 R_Mesh_TexBind(0, layer->texture);
9883 R_Mesh_TexMatrix(0, &layer->texmatrix);
9884 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9885 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9886 R_Mesh_TexBind(1, 0);
9887 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9888 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9890 case TEXTURELAYERTYPE_FOG:
9891 // singletexture fogging
9894 R_Mesh_TexBind(0, layer->texture);
9895 R_Mesh_TexMatrix(0, &layer->texmatrix);
9896 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9897 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9901 R_Mesh_TexBind(0, 0);
9902 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9904 R_Mesh_TexBind(1, 0);
9905 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9906 // generate a color array for the fog pass
9907 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9908 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9912 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9915 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9917 GL_DepthFunc(GL_LEQUAL);
9918 GL_AlphaTest(false);
9922 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9924 // OpenGL 1.1 - crusty old voodoo path
9927 const texturelayer_t *layer;
9928 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);
9929 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9931 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9933 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9935 if (layerindex == 0)
9939 GL_AlphaTest(false);
9940 GL_DepthFunc(GL_EQUAL);
9943 GL_DepthMask(layer->depthmask && writedepth);
9944 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9945 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9946 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9947 switch (layer->type)
9949 case TEXTURELAYERTYPE_LITTEXTURE:
9950 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9952 // two-pass lit texture with 2x rgbscale
9953 // first the lightmap pass
9954 R_Mesh_TexBind(0, r_texture_white);
9955 R_Mesh_TexMatrix(0, NULL);
9956 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9957 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9958 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9959 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9960 else if (FAKELIGHT_ENABLED)
9961 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9962 else if (rsurface.uselightmaptexture)
9963 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9965 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9966 // then apply the texture to it
9967 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9968 R_Mesh_TexBind(0, layer->texture);
9969 R_Mesh_TexMatrix(0, &layer->texmatrix);
9970 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9971 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9972 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);
9976 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9977 R_Mesh_TexBind(0, layer->texture);
9978 R_Mesh_TexMatrix(0, &layer->texmatrix);
9979 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9980 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9981 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9982 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);
9984 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);
9987 case TEXTURELAYERTYPE_TEXTURE:
9988 // singletexture unlit texture with transparency support
9989 R_Mesh_TexBind(0, layer->texture);
9990 R_Mesh_TexMatrix(0, &layer->texmatrix);
9991 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9992 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9993 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);
9995 case TEXTURELAYERTYPE_FOG:
9996 // singletexture fogging
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);
10006 R_Mesh_TexBind(0, 0);
10007 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10009 // generate a color array for the fog pass
10010 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10011 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10015 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10018 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10020 GL_DepthFunc(GL_LEQUAL);
10021 GL_AlphaTest(false);
10025 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10029 r_vertexgeneric_t *batchvertex;
10032 // R_Mesh_ResetTextureState();
10033 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10035 if(rsurface.texture && rsurface.texture->currentskinframe)
10037 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10038 c[3] *= rsurface.texture->currentalpha;
10048 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10050 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10051 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10052 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10055 // brighten it up (as texture value 127 means "unlit")
10056 c[0] *= 2 * r_refdef.view.colorscale;
10057 c[1] *= 2 * r_refdef.view.colorscale;
10058 c[2] *= 2 * r_refdef.view.colorscale;
10060 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10061 c[3] *= r_wateralpha.value;
10063 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10065 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10066 GL_DepthMask(false);
10068 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10070 GL_BlendFunc(GL_ONE, GL_ONE);
10071 GL_DepthMask(false);
10073 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10075 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10076 GL_DepthMask(false);
10078 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10080 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10081 GL_DepthMask(false);
10085 GL_BlendFunc(GL_ONE, GL_ZERO);
10086 GL_DepthMask(writedepth);
10089 if (r_showsurfaces.integer == 3)
10091 rsurface.passcolor4f = NULL;
10093 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10095 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10097 rsurface.passcolor4f = NULL;
10098 rsurface.passcolor4f_vertexbuffer = 0;
10099 rsurface.passcolor4f_bufferoffset = 0;
10101 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10103 qboolean applycolor = true;
10106 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10108 r_refdef.lightmapintensity = 1;
10109 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10110 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10112 else if (FAKELIGHT_ENABLED)
10114 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10116 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10117 RSurf_DrawBatch_GL11_ApplyFakeLight();
10118 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10122 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10124 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10125 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10126 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10129 if(!rsurface.passcolor4f)
10130 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10132 RSurf_DrawBatch_GL11_ApplyAmbient();
10133 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10134 if(r_refdef.fogenabled)
10135 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10136 RSurf_DrawBatch_GL11_ClampColor();
10138 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10139 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10142 else if (!r_refdef.view.showdebug)
10144 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10145 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10146 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10148 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10149 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10151 R_Mesh_PrepareVertices_Generic_Unlock();
10154 else if (r_showsurfaces.integer == 4)
10156 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10157 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10158 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10160 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10161 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10162 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10164 R_Mesh_PrepareVertices_Generic_Unlock();
10167 else if (r_showsurfaces.integer == 2)
10170 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10171 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10172 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10174 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10175 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10176 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10177 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10178 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10179 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10180 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10182 R_Mesh_PrepareVertices_Generic_Unlock();
10183 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10187 int texturesurfaceindex;
10189 const msurface_t *surface;
10190 float surfacecolor4f[4];
10191 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10192 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10194 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10196 surface = texturesurfacelist[texturesurfaceindex];
10197 k = (int)(((size_t)surface) / sizeof(msurface_t));
10198 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10199 for (j = 0;j < surface->num_vertices;j++)
10201 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10202 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10206 R_Mesh_PrepareVertices_Generic_Unlock();
10211 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10214 RSurf_SetupDepthAndCulling();
10215 if (r_showsurfaces.integer)
10217 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10220 switch (vid.renderpath)
10222 case RENDERPATH_GL20:
10223 case RENDERPATH_D3D9:
10224 case RENDERPATH_D3D10:
10225 case RENDERPATH_D3D11:
10226 case RENDERPATH_SOFT:
10227 case RENDERPATH_GLES2:
10228 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10230 case RENDERPATH_GL13:
10231 case RENDERPATH_GLES1:
10232 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10234 case RENDERPATH_GL11:
10235 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10241 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10244 RSurf_SetupDepthAndCulling();
10245 if (r_showsurfaces.integer)
10247 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10250 switch (vid.renderpath)
10252 case RENDERPATH_GL20:
10253 case RENDERPATH_D3D9:
10254 case RENDERPATH_D3D10:
10255 case RENDERPATH_D3D11:
10256 case RENDERPATH_SOFT:
10257 case RENDERPATH_GLES2:
10258 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10260 case RENDERPATH_GL13:
10261 case RENDERPATH_GLES1:
10262 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10264 case RENDERPATH_GL11:
10265 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10271 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10274 int texturenumsurfaces, endsurface;
10275 texture_t *texture;
10276 const msurface_t *surface;
10277 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10279 // if the model is static it doesn't matter what value we give for
10280 // wantnormals and wanttangents, so this logic uses only rules applicable
10281 // to a model, knowing that they are meaningless otherwise
10282 if (ent == r_refdef.scene.worldentity)
10283 RSurf_ActiveWorldEntity();
10284 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10285 RSurf_ActiveModelEntity(ent, false, false, false);
10288 switch (vid.renderpath)
10290 case RENDERPATH_GL20:
10291 case RENDERPATH_D3D9:
10292 case RENDERPATH_D3D10:
10293 case RENDERPATH_D3D11:
10294 case RENDERPATH_SOFT:
10295 case RENDERPATH_GLES2:
10296 RSurf_ActiveModelEntity(ent, true, true, false);
10298 case RENDERPATH_GL11:
10299 case RENDERPATH_GL13:
10300 case RENDERPATH_GLES1:
10301 RSurf_ActiveModelEntity(ent, true, false, false);
10306 if (r_transparentdepthmasking.integer)
10308 qboolean setup = false;
10309 for (i = 0;i < numsurfaces;i = j)
10312 surface = rsurface.modelsurfaces + surfacelist[i];
10313 texture = surface->texture;
10314 rsurface.texture = R_GetCurrentTexture(texture);
10315 rsurface.lightmaptexture = NULL;
10316 rsurface.deluxemaptexture = NULL;
10317 rsurface.uselightmaptexture = false;
10318 // scan ahead until we find a different texture
10319 endsurface = min(i + 1024, numsurfaces);
10320 texturenumsurfaces = 0;
10321 texturesurfacelist[texturenumsurfaces++] = surface;
10322 for (;j < endsurface;j++)
10324 surface = rsurface.modelsurfaces + surfacelist[j];
10325 if (texture != surface->texture)
10327 texturesurfacelist[texturenumsurfaces++] = surface;
10329 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10331 // render the range of surfaces as depth
10335 GL_ColorMask(0,0,0,0);
10337 GL_DepthTest(true);
10338 GL_BlendFunc(GL_ONE, GL_ZERO);
10339 GL_DepthMask(true);
10340 // R_Mesh_ResetTextureState();
10341 R_SetupShader_DepthOrShadow(false);
10343 RSurf_SetupDepthAndCulling();
10344 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10345 if (rsurface.batchvertex3fbuffer)
10346 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10348 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10352 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10355 for (i = 0;i < numsurfaces;i = j)
10358 surface = rsurface.modelsurfaces + surfacelist[i];
10359 texture = surface->texture;
10360 rsurface.texture = R_GetCurrentTexture(texture);
10361 // scan ahead until we find a different texture
10362 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10363 texturenumsurfaces = 0;
10364 texturesurfacelist[texturenumsurfaces++] = surface;
10365 if(FAKELIGHT_ENABLED)
10367 rsurface.lightmaptexture = NULL;
10368 rsurface.deluxemaptexture = NULL;
10369 rsurface.uselightmaptexture = false;
10370 for (;j < endsurface;j++)
10372 surface = rsurface.modelsurfaces + surfacelist[j];
10373 if (texture != surface->texture)
10375 texturesurfacelist[texturenumsurfaces++] = surface;
10380 rsurface.lightmaptexture = surface->lightmaptexture;
10381 rsurface.deluxemaptexture = surface->deluxemaptexture;
10382 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10383 for (;j < endsurface;j++)
10385 surface = rsurface.modelsurfaces + surfacelist[j];
10386 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10388 texturesurfacelist[texturenumsurfaces++] = surface;
10391 // render the range of surfaces
10392 if (ent == r_refdef.scene.worldentity)
10393 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10395 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10397 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10400 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10402 // transparent surfaces get pushed off into the transparent queue
10403 int surfacelistindex;
10404 const msurface_t *surface;
10405 vec3_t tempcenter, center;
10406 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10408 surface = texturesurfacelist[surfacelistindex];
10409 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10410 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10411 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10412 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10413 if (queueentity->transparent_offset) // transparent offset
10415 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10416 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10417 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10419 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10423 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10425 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10427 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10429 RSurf_SetupDepthAndCulling();
10430 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10431 if (rsurface.batchvertex3fbuffer)
10432 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10434 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10438 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10440 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10443 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10446 if (!rsurface.texture->currentnumlayers)
10448 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10449 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10451 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10453 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10454 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10455 else if (!rsurface.texture->currentnumlayers)
10457 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10459 // in the deferred case, transparent surfaces were queued during prepass
10460 if (!r_shadow_usingdeferredprepass)
10461 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10465 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10466 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10471 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10474 texture_t *texture;
10475 R_FrameData_SetMark();
10476 // break the surface list down into batches by texture and use of lightmapping
10477 for (i = 0;i < numsurfaces;i = j)
10480 // texture is the base texture pointer, rsurface.texture is the
10481 // current frame/skin the texture is directing us to use (for example
10482 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10483 // use skin 1 instead)
10484 texture = surfacelist[i]->texture;
10485 rsurface.texture = R_GetCurrentTexture(texture);
10486 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10488 // if this texture is not the kind we want, skip ahead to the next one
10489 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10493 if(FAKELIGHT_ENABLED || depthonly || prepass)
10495 rsurface.lightmaptexture = NULL;
10496 rsurface.deluxemaptexture = NULL;
10497 rsurface.uselightmaptexture = false;
10498 // simply scan ahead until we find a different texture or lightmap state
10499 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10504 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10505 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10506 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10507 // simply scan ahead until we find a different texture or lightmap state
10508 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10511 // render the range of surfaces
10512 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10514 R_FrameData_ReturnToMark();
10517 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10521 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10524 if (!rsurface.texture->currentnumlayers)
10526 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10527 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10529 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10531 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10532 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10533 else if (!rsurface.texture->currentnumlayers)
10535 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10537 // in the deferred case, transparent surfaces were queued during prepass
10538 if (!r_shadow_usingdeferredprepass)
10539 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10543 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10544 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10549 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10552 texture_t *texture;
10553 R_FrameData_SetMark();
10554 // break the surface list down into batches by texture and use of lightmapping
10555 for (i = 0;i < numsurfaces;i = j)
10558 // texture is the base texture pointer, rsurface.texture is the
10559 // current frame/skin the texture is directing us to use (for example
10560 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10561 // use skin 1 instead)
10562 texture = surfacelist[i]->texture;
10563 rsurface.texture = R_GetCurrentTexture(texture);
10564 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10566 // if this texture is not the kind we want, skip ahead to the next one
10567 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10571 if(FAKELIGHT_ENABLED || depthonly || prepass)
10573 rsurface.lightmaptexture = NULL;
10574 rsurface.deluxemaptexture = NULL;
10575 rsurface.uselightmaptexture = false;
10576 // simply scan ahead until we find a different texture or lightmap state
10577 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10582 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10583 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10584 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10585 // simply scan ahead until we find a different texture or lightmap state
10586 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10589 // render the range of surfaces
10590 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10592 R_FrameData_ReturnToMark();
10595 float locboxvertex3f[6*4*3] =
10597 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10598 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10599 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10600 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10601 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10602 1,0,0, 0,0,0, 0,1,0, 1,1,0
10605 unsigned short locboxelements[6*2*3] =
10610 12,13,14, 12,14,15,
10611 16,17,18, 16,18,19,
10615 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10618 cl_locnode_t *loc = (cl_locnode_t *)ent;
10620 float vertex3f[6*4*3];
10622 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10623 GL_DepthMask(false);
10624 GL_DepthRange(0, 1);
10625 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10626 GL_DepthTest(true);
10627 GL_CullFace(GL_NONE);
10628 R_EntityMatrix(&identitymatrix);
10630 // R_Mesh_ResetTextureState();
10632 i = surfacelist[0];
10633 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10634 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10635 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10636 surfacelist[0] < 0 ? 0.5f : 0.125f);
10638 if (VectorCompare(loc->mins, loc->maxs))
10640 VectorSet(size, 2, 2, 2);
10641 VectorMA(loc->mins, -0.5f, size, mins);
10645 VectorCopy(loc->mins, mins);
10646 VectorSubtract(loc->maxs, loc->mins, size);
10649 for (i = 0;i < 6*4*3;)
10650 for (j = 0;j < 3;j++, i++)
10651 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10653 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10654 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10655 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10658 void R_DrawLocs(void)
10661 cl_locnode_t *loc, *nearestloc;
10663 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10664 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10666 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10667 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10671 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10673 if (decalsystem->decals)
10674 Mem_Free(decalsystem->decals);
10675 memset(decalsystem, 0, sizeof(*decalsystem));
10678 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)
10681 tridecal_t *decals;
10684 // expand or initialize the system
10685 if (decalsystem->maxdecals <= decalsystem->numdecals)
10687 decalsystem_t old = *decalsystem;
10688 qboolean useshortelements;
10689 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10690 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10691 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)));
10692 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10693 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10694 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10695 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10696 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10697 if (decalsystem->numdecals)
10698 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10700 Mem_Free(old.decals);
10701 for (i = 0;i < decalsystem->maxdecals*3;i++)
10702 decalsystem->element3i[i] = i;
10703 if (useshortelements)
10704 for (i = 0;i < decalsystem->maxdecals*3;i++)
10705 decalsystem->element3s[i] = i;
10708 // grab a decal and search for another free slot for the next one
10709 decals = decalsystem->decals;
10710 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10711 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10713 decalsystem->freedecal = i;
10714 if (decalsystem->numdecals <= i)
10715 decalsystem->numdecals = i + 1;
10717 // initialize the decal
10719 decal->triangleindex = triangleindex;
10720 decal->surfaceindex = surfaceindex;
10721 decal->decalsequence = decalsequence;
10722 decal->color4f[0][0] = c0[0];
10723 decal->color4f[0][1] = c0[1];
10724 decal->color4f[0][2] = c0[2];
10725 decal->color4f[0][3] = 1;
10726 decal->color4f[1][0] = c1[0];
10727 decal->color4f[1][1] = c1[1];
10728 decal->color4f[1][2] = c1[2];
10729 decal->color4f[1][3] = 1;
10730 decal->color4f[2][0] = c2[0];
10731 decal->color4f[2][1] = c2[1];
10732 decal->color4f[2][2] = c2[2];
10733 decal->color4f[2][3] = 1;
10734 decal->vertex3f[0][0] = v0[0];
10735 decal->vertex3f[0][1] = v0[1];
10736 decal->vertex3f[0][2] = v0[2];
10737 decal->vertex3f[1][0] = v1[0];
10738 decal->vertex3f[1][1] = v1[1];
10739 decal->vertex3f[1][2] = v1[2];
10740 decal->vertex3f[2][0] = v2[0];
10741 decal->vertex3f[2][1] = v2[1];
10742 decal->vertex3f[2][2] = v2[2];
10743 decal->texcoord2f[0][0] = t0[0];
10744 decal->texcoord2f[0][1] = t0[1];
10745 decal->texcoord2f[1][0] = t1[0];
10746 decal->texcoord2f[1][1] = t1[1];
10747 decal->texcoord2f[2][0] = t2[0];
10748 decal->texcoord2f[2][1] = t2[1];
10749 TriangleNormal(v0, v1, v2, decal->plane);
10750 VectorNormalize(decal->plane);
10751 decal->plane[3] = DotProduct(v0, decal->plane);
10754 extern cvar_t cl_decals_bias;
10755 extern cvar_t cl_decals_models;
10756 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10757 // baseparms, parms, temps
10758 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)
10763 const float *vertex3f;
10764 const float *normal3f;
10766 float points[2][9][3];
10773 e = rsurface.modelelement3i + 3*triangleindex;
10775 vertex3f = rsurface.modelvertex3f;
10776 normal3f = rsurface.modelnormal3f;
10780 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10782 index = 3*e[cornerindex];
10783 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10788 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10790 index = 3*e[cornerindex];
10791 VectorCopy(vertex3f + index, v[cornerindex]);
10796 //TriangleNormal(v[0], v[1], v[2], normal);
10797 //if (DotProduct(normal, localnormal) < 0.0f)
10799 // clip by each of the box planes formed from the projection matrix
10800 // if anything survives, we emit the decal
10801 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]);
10804 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]);
10807 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]);
10810 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]);
10813 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]);
10816 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]);
10819 // some part of the triangle survived, so we have to accept it...
10822 // dynamic always uses the original triangle
10824 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10826 index = 3*e[cornerindex];
10827 VectorCopy(vertex3f + index, v[cornerindex]);
10830 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10832 // convert vertex positions to texcoords
10833 Matrix4x4_Transform(projection, v[cornerindex], temp);
10834 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10835 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10836 // calculate distance fade from the projection origin
10837 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10838 f = bound(0.0f, f, 1.0f);
10839 c[cornerindex][0] = r * f;
10840 c[cornerindex][1] = g * f;
10841 c[cornerindex][2] = b * f;
10842 c[cornerindex][3] = 1.0f;
10843 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10846 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);
10848 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10849 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);
10851 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)
10853 matrix4x4_t projection;
10854 decalsystem_t *decalsystem;
10857 const msurface_t *surface;
10858 const msurface_t *surfaces;
10859 const int *surfacelist;
10860 const texture_t *texture;
10862 int numsurfacelist;
10863 int surfacelistindex;
10866 float localorigin[3];
10867 float localnormal[3];
10868 float localmins[3];
10869 float localmaxs[3];
10872 float planes[6][4];
10875 int bih_triangles_count;
10876 int bih_triangles[256];
10877 int bih_surfaces[256];
10879 decalsystem = &ent->decalsystem;
10880 model = ent->model;
10881 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10883 R_DecalSystem_Reset(&ent->decalsystem);
10887 if (!model->brush.data_leafs && !cl_decals_models.integer)
10889 if (decalsystem->model)
10890 R_DecalSystem_Reset(decalsystem);
10894 if (decalsystem->model != model)
10895 R_DecalSystem_Reset(decalsystem);
10896 decalsystem->model = model;
10898 RSurf_ActiveModelEntity(ent, true, false, false);
10900 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10901 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10902 VectorNormalize(localnormal);
10903 localsize = worldsize*rsurface.inversematrixscale;
10904 localmins[0] = localorigin[0] - localsize;
10905 localmins[1] = localorigin[1] - localsize;
10906 localmins[2] = localorigin[2] - localsize;
10907 localmaxs[0] = localorigin[0] + localsize;
10908 localmaxs[1] = localorigin[1] + localsize;
10909 localmaxs[2] = localorigin[2] + localsize;
10911 //VectorCopy(localnormal, planes[4]);
10912 //VectorVectors(planes[4], planes[2], planes[0]);
10913 AnglesFromVectors(angles, localnormal, NULL, false);
10914 AngleVectors(angles, planes[0], planes[2], planes[4]);
10915 VectorNegate(planes[0], planes[1]);
10916 VectorNegate(planes[2], planes[3]);
10917 VectorNegate(planes[4], planes[5]);
10918 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10919 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10920 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10921 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10922 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10923 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10928 matrix4x4_t forwardprojection;
10929 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10930 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10935 float projectionvector[4][3];
10936 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10937 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10938 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10939 projectionvector[0][0] = planes[0][0] * ilocalsize;
10940 projectionvector[0][1] = planes[1][0] * ilocalsize;
10941 projectionvector[0][2] = planes[2][0] * ilocalsize;
10942 projectionvector[1][0] = planes[0][1] * ilocalsize;
10943 projectionvector[1][1] = planes[1][1] * ilocalsize;
10944 projectionvector[1][2] = planes[2][1] * ilocalsize;
10945 projectionvector[2][0] = planes[0][2] * ilocalsize;
10946 projectionvector[2][1] = planes[1][2] * ilocalsize;
10947 projectionvector[2][2] = planes[2][2] * ilocalsize;
10948 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10949 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10950 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10951 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10955 dynamic = model->surfmesh.isanimated;
10956 numsurfacelist = model->nummodelsurfaces;
10957 surfacelist = model->sortedmodelsurfaces;
10958 surfaces = model->data_surfaces;
10961 bih_triangles_count = -1;
10964 if(model->render_bih.numleafs)
10965 bih = &model->render_bih;
10966 else if(model->collision_bih.numleafs)
10967 bih = &model->collision_bih;
10970 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10971 if(bih_triangles_count == 0)
10973 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10975 if(bih_triangles_count > 0)
10977 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10979 surfaceindex = bih_surfaces[triangleindex];
10980 surface = surfaces + surfaceindex;
10981 texture = surface->texture;
10982 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10984 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10986 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10991 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10993 surfaceindex = surfacelist[surfacelistindex];
10994 surface = surfaces + surfaceindex;
10995 // check cull box first because it rejects more than any other check
10996 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10998 // skip transparent surfaces
10999 texture = surface->texture;
11000 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11002 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11004 numtriangles = surface->num_triangles;
11005 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11006 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11011 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11012 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)
11014 int renderentityindex;
11015 float worldmins[3];
11016 float worldmaxs[3];
11017 entity_render_t *ent;
11019 if (!cl_decals_newsystem.integer)
11022 worldmins[0] = worldorigin[0] - worldsize;
11023 worldmins[1] = worldorigin[1] - worldsize;
11024 worldmins[2] = worldorigin[2] - worldsize;
11025 worldmaxs[0] = worldorigin[0] + worldsize;
11026 worldmaxs[1] = worldorigin[1] + worldsize;
11027 worldmaxs[2] = worldorigin[2] + worldsize;
11029 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11031 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11033 ent = r_refdef.scene.entities[renderentityindex];
11034 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11037 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11041 typedef struct r_decalsystem_splatqueue_s
11043 vec3_t worldorigin;
11044 vec3_t worldnormal;
11050 r_decalsystem_splatqueue_t;
11052 int r_decalsystem_numqueued = 0;
11053 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11055 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)
11057 r_decalsystem_splatqueue_t *queue;
11059 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11062 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11063 VectorCopy(worldorigin, queue->worldorigin);
11064 VectorCopy(worldnormal, queue->worldnormal);
11065 Vector4Set(queue->color, r, g, b, a);
11066 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11067 queue->worldsize = worldsize;
11068 queue->decalsequence = cl.decalsequence++;
11071 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11074 r_decalsystem_splatqueue_t *queue;
11076 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11077 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);
11078 r_decalsystem_numqueued = 0;
11081 extern cvar_t cl_decals_max;
11082 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11085 decalsystem_t *decalsystem = &ent->decalsystem;
11092 if (!decalsystem->numdecals)
11095 if (r_showsurfaces.integer)
11098 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11100 R_DecalSystem_Reset(decalsystem);
11104 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11105 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11107 if (decalsystem->lastupdatetime)
11108 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11111 decalsystem->lastupdatetime = r_refdef.scene.time;
11112 decal = decalsystem->decals;
11113 numdecals = decalsystem->numdecals;
11115 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11117 if (decal->color4f[0][3])
11119 decal->lived += frametime;
11120 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11122 memset(decal, 0, sizeof(*decal));
11123 if (decalsystem->freedecal > i)
11124 decalsystem->freedecal = i;
11128 decal = decalsystem->decals;
11129 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11132 // collapse the array by shuffling the tail decals into the gaps
11135 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11136 decalsystem->freedecal++;
11137 if (decalsystem->freedecal == numdecals)
11139 decal[decalsystem->freedecal] = decal[--numdecals];
11142 decalsystem->numdecals = numdecals;
11144 if (numdecals <= 0)
11146 // if there are no decals left, reset decalsystem
11147 R_DecalSystem_Reset(decalsystem);
11151 extern skinframe_t *decalskinframe;
11152 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11155 decalsystem_t *decalsystem = &ent->decalsystem;
11164 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11167 numdecals = decalsystem->numdecals;
11171 if (r_showsurfaces.integer)
11174 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11176 R_DecalSystem_Reset(decalsystem);
11180 // if the model is static it doesn't matter what value we give for
11181 // wantnormals and wanttangents, so this logic uses only rules applicable
11182 // to a model, knowing that they are meaningless otherwise
11183 if (ent == r_refdef.scene.worldentity)
11184 RSurf_ActiveWorldEntity();
11186 RSurf_ActiveModelEntity(ent, false, false, false);
11188 decalsystem->lastupdatetime = r_refdef.scene.time;
11189 decal = decalsystem->decals;
11191 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11193 // update vertex positions for animated models
11194 v3f = decalsystem->vertex3f;
11195 c4f = decalsystem->color4f;
11196 t2f = decalsystem->texcoord2f;
11197 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11199 if (!decal->color4f[0][3])
11202 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11206 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11209 // update color values for fading decals
11210 if (decal->lived >= cl_decals_time.value)
11211 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11215 c4f[ 0] = decal->color4f[0][0] * alpha;
11216 c4f[ 1] = decal->color4f[0][1] * alpha;
11217 c4f[ 2] = decal->color4f[0][2] * alpha;
11219 c4f[ 4] = decal->color4f[1][0] * alpha;
11220 c4f[ 5] = decal->color4f[1][1] * alpha;
11221 c4f[ 6] = decal->color4f[1][2] * alpha;
11223 c4f[ 8] = decal->color4f[2][0] * alpha;
11224 c4f[ 9] = decal->color4f[2][1] * alpha;
11225 c4f[10] = decal->color4f[2][2] * alpha;
11228 t2f[0] = decal->texcoord2f[0][0];
11229 t2f[1] = decal->texcoord2f[0][1];
11230 t2f[2] = decal->texcoord2f[1][0];
11231 t2f[3] = decal->texcoord2f[1][1];
11232 t2f[4] = decal->texcoord2f[2][0];
11233 t2f[5] = decal->texcoord2f[2][1];
11235 // update vertex positions for animated models
11236 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11238 e = rsurface.modelelement3i + 3*decal->triangleindex;
11239 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11240 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11241 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11245 VectorCopy(decal->vertex3f[0], v3f);
11246 VectorCopy(decal->vertex3f[1], v3f + 3);
11247 VectorCopy(decal->vertex3f[2], v3f + 6);
11250 if (r_refdef.fogenabled)
11252 alpha = RSurf_FogVertex(v3f);
11253 VectorScale(c4f, alpha, c4f);
11254 alpha = RSurf_FogVertex(v3f + 3);
11255 VectorScale(c4f + 4, alpha, c4f + 4);
11256 alpha = RSurf_FogVertex(v3f + 6);
11257 VectorScale(c4f + 8, alpha, c4f + 8);
11268 r_refdef.stats.drawndecals += numtris;
11270 // now render the decals all at once
11271 // (this assumes they all use one particle font texture!)
11272 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);
11273 // R_Mesh_ResetTextureState();
11274 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11275 GL_DepthMask(false);
11276 GL_DepthRange(0, 1);
11277 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11278 GL_DepthTest(true);
11279 GL_CullFace(GL_NONE);
11280 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11281 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11282 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11286 static void R_DrawModelDecals(void)
11290 // fade faster when there are too many decals
11291 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11292 for (i = 0;i < r_refdef.scene.numentities;i++)
11293 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11295 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11296 for (i = 0;i < r_refdef.scene.numentities;i++)
11297 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11298 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11300 R_DecalSystem_ApplySplatEntitiesQueue();
11302 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11303 for (i = 0;i < r_refdef.scene.numentities;i++)
11304 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11306 r_refdef.stats.totaldecals += numdecals;
11308 if (r_showsurfaces.integer)
11311 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11313 for (i = 0;i < r_refdef.scene.numentities;i++)
11315 if (!r_refdef.viewcache.entityvisible[i])
11317 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11318 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11322 extern cvar_t mod_collision_bih;
11323 void R_DrawDebugModel(void)
11325 entity_render_t *ent = rsurface.entity;
11326 int i, j, k, l, flagsmask;
11327 const msurface_t *surface;
11328 dp_model_t *model = ent->model;
11331 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11334 if (r_showoverdraw.value > 0)
11336 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11337 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11338 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11339 GL_DepthTest(false);
11340 GL_DepthMask(false);
11341 GL_DepthRange(0, 1);
11342 GL_BlendFunc(GL_ONE, GL_ONE);
11343 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11345 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11347 rsurface.texture = R_GetCurrentTexture(surface->texture);
11348 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11350 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11351 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11352 if (!rsurface.texture->currentlayers->depthmask)
11353 GL_Color(c, 0, 0, 1.0f);
11354 else if (ent == r_refdef.scene.worldentity)
11355 GL_Color(c, c, c, 1.0f);
11357 GL_Color(0, c, 0, 1.0f);
11358 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11362 rsurface.texture = NULL;
11365 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11367 // R_Mesh_ResetTextureState();
11368 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11369 GL_DepthRange(0, 1);
11370 GL_DepthTest(!r_showdisabledepthtest.integer);
11371 GL_DepthMask(false);
11372 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11374 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11378 qboolean cullbox = ent == r_refdef.scene.worldentity;
11379 const q3mbrush_t *brush;
11380 const bih_t *bih = &model->collision_bih;
11381 const bih_leaf_t *bihleaf;
11382 float vertex3f[3][3];
11383 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11385 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11387 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11389 switch (bihleaf->type)
11392 brush = model->brush.data_brushes + bihleaf->itemindex;
11393 if (brush->colbrushf && brush->colbrushf->numtriangles)
11395 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);
11396 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11397 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11400 case BIH_COLLISIONTRIANGLE:
11401 triangleindex = bihleaf->itemindex;
11402 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11403 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11404 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11405 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);
11406 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11407 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11409 case BIH_RENDERTRIANGLE:
11410 triangleindex = bihleaf->itemindex;
11411 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11412 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11413 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11414 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);
11415 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11416 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11422 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11425 if (r_showtris.integer && qglPolygonMode)
11427 if (r_showdisabledepthtest.integer)
11429 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11430 GL_DepthMask(false);
11434 GL_BlendFunc(GL_ONE, GL_ZERO);
11435 GL_DepthMask(true);
11437 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11438 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11440 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11442 rsurface.texture = R_GetCurrentTexture(surface->texture);
11443 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11445 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11446 if (!rsurface.texture->currentlayers->depthmask)
11447 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11448 else if (ent == r_refdef.scene.worldentity)
11449 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11451 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11452 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11456 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11457 rsurface.texture = NULL;
11460 if (r_shownormals.value != 0 && qglBegin)
11462 if (r_showdisabledepthtest.integer)
11464 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11465 GL_DepthMask(false);
11469 GL_BlendFunc(GL_ONE, GL_ZERO);
11470 GL_DepthMask(true);
11472 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11474 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11476 rsurface.texture = R_GetCurrentTexture(surface->texture);
11477 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11479 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11480 qglBegin(GL_LINES);
11481 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11483 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11485 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11486 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11487 qglVertex3f(v[0], v[1], v[2]);
11488 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11489 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11490 qglVertex3f(v[0], v[1], v[2]);
11493 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11495 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11497 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11498 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11499 qglVertex3f(v[0], v[1], v[2]);
11500 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11501 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11502 qglVertex3f(v[0], v[1], v[2]);
11505 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11507 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11509 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11510 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11511 qglVertex3f(v[0], v[1], v[2]);
11512 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11513 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11514 qglVertex3f(v[0], v[1], v[2]);
11517 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11519 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11521 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11522 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11523 qglVertex3f(v[0], v[1], v[2]);
11524 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11525 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11526 qglVertex3f(v[0], v[1], v[2]);
11533 rsurface.texture = NULL;
11538 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11539 int r_maxsurfacelist = 0;
11540 const msurface_t **r_surfacelist = NULL;
11541 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11543 int i, j, endj, flagsmask;
11544 dp_model_t *model = r_refdef.scene.worldmodel;
11545 msurface_t *surfaces;
11546 unsigned char *update;
11547 int numsurfacelist = 0;
11551 if (r_maxsurfacelist < model->num_surfaces)
11553 r_maxsurfacelist = model->num_surfaces;
11555 Mem_Free((msurface_t**)r_surfacelist);
11556 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11559 RSurf_ActiveWorldEntity();
11561 surfaces = model->data_surfaces;
11562 update = model->brushq1.lightmapupdateflags;
11564 // update light styles on this submodel
11565 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11567 model_brush_lightstyleinfo_t *style;
11568 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11570 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11572 int *list = style->surfacelist;
11573 style->value = r_refdef.scene.lightstylevalue[style->style];
11574 for (j = 0;j < style->numsurfaces;j++)
11575 update[list[j]] = true;
11580 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11584 R_DrawDebugModel();
11585 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11589 rsurface.lightmaptexture = NULL;
11590 rsurface.deluxemaptexture = NULL;
11591 rsurface.uselightmaptexture = false;
11592 rsurface.texture = NULL;
11593 rsurface.rtlight = NULL;
11594 numsurfacelist = 0;
11595 // add visible surfaces to draw list
11596 for (i = 0;i < model->nummodelsurfaces;i++)
11598 j = model->sortedmodelsurfaces[i];
11599 if (r_refdef.viewcache.world_surfacevisible[j])
11600 r_surfacelist[numsurfacelist++] = surfaces + j;
11602 // update lightmaps if needed
11603 if (model->brushq1.firstrender)
11605 model->brushq1.firstrender = false;
11606 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11608 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11612 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11613 if (r_refdef.viewcache.world_surfacevisible[j])
11615 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11617 // don't do anything if there were no surfaces
11618 if (!numsurfacelist)
11620 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11623 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11625 // add to stats if desired
11626 if (r_speeds.integer && !skysurfaces && !depthonly)
11628 r_refdef.stats.world_surfaces += numsurfacelist;
11629 for (j = 0;j < numsurfacelist;j++)
11630 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11633 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11636 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11638 int i, j, endj, flagsmask;
11639 dp_model_t *model = ent->model;
11640 msurface_t *surfaces;
11641 unsigned char *update;
11642 int numsurfacelist = 0;
11646 if (r_maxsurfacelist < model->num_surfaces)
11648 r_maxsurfacelist = model->num_surfaces;
11650 Mem_Free((msurface_t **)r_surfacelist);
11651 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11654 // if the model is static it doesn't matter what value we give for
11655 // wantnormals and wanttangents, so this logic uses only rules applicable
11656 // to a model, knowing that they are meaningless otherwise
11657 if (ent == r_refdef.scene.worldentity)
11658 RSurf_ActiveWorldEntity();
11659 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11660 RSurf_ActiveModelEntity(ent, false, false, false);
11662 RSurf_ActiveModelEntity(ent, true, true, true);
11663 else if (depthonly)
11665 switch (vid.renderpath)
11667 case RENDERPATH_GL20:
11668 case RENDERPATH_D3D9:
11669 case RENDERPATH_D3D10:
11670 case RENDERPATH_D3D11:
11671 case RENDERPATH_SOFT:
11672 case RENDERPATH_GLES2:
11673 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11675 case RENDERPATH_GL11:
11676 case RENDERPATH_GL13:
11677 case RENDERPATH_GLES1:
11678 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11684 switch (vid.renderpath)
11686 case RENDERPATH_GL20:
11687 case RENDERPATH_D3D9:
11688 case RENDERPATH_D3D10:
11689 case RENDERPATH_D3D11:
11690 case RENDERPATH_SOFT:
11691 case RENDERPATH_GLES2:
11692 RSurf_ActiveModelEntity(ent, true, true, false);
11694 case RENDERPATH_GL11:
11695 case RENDERPATH_GL13:
11696 case RENDERPATH_GLES1:
11697 RSurf_ActiveModelEntity(ent, true, false, false);
11702 surfaces = model->data_surfaces;
11703 update = model->brushq1.lightmapupdateflags;
11705 // update light styles
11706 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11708 model_brush_lightstyleinfo_t *style;
11709 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11711 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11713 int *list = style->surfacelist;
11714 style->value = r_refdef.scene.lightstylevalue[style->style];
11715 for (j = 0;j < style->numsurfaces;j++)
11716 update[list[j]] = true;
11721 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11725 R_DrawDebugModel();
11726 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11730 rsurface.lightmaptexture = NULL;
11731 rsurface.deluxemaptexture = NULL;
11732 rsurface.uselightmaptexture = false;
11733 rsurface.texture = NULL;
11734 rsurface.rtlight = NULL;
11735 numsurfacelist = 0;
11736 // add visible surfaces to draw list
11737 for (i = 0;i < model->nummodelsurfaces;i++)
11738 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11739 // don't do anything if there were no surfaces
11740 if (!numsurfacelist)
11742 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11745 // update lightmaps if needed
11749 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11754 R_BuildLightMap(ent, surfaces + j);
11759 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11761 R_BuildLightMap(ent, surfaces + j);
11762 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11764 // add to stats if desired
11765 if (r_speeds.integer && !skysurfaces && !depthonly)
11767 r_refdef.stats.entities_surfaces += numsurfacelist;
11768 for (j = 0;j < numsurfacelist;j++)
11769 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11772 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11775 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11777 static texture_t texture;
11778 static msurface_t surface;
11779 const msurface_t *surfacelist = &surface;
11781 // fake enough texture and surface state to render this geometry
11783 texture.update_lastrenderframe = -1; // regenerate this texture
11784 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11785 texture.currentskinframe = skinframe;
11786 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11787 texture.offsetmapping = OFFSETMAPPING_OFF;
11788 texture.offsetscale = 1;
11789 texture.specularscalemod = 1;
11790 texture.specularpowermod = 1;
11792 surface.texture = &texture;
11793 surface.num_triangles = numtriangles;
11794 surface.num_firsttriangle = firsttriangle;
11795 surface.num_vertices = numvertices;
11796 surface.num_firstvertex = firstvertex;
11799 rsurface.texture = R_GetCurrentTexture(surface.texture);
11800 rsurface.lightmaptexture = NULL;
11801 rsurface.deluxemaptexture = NULL;
11802 rsurface.uselightmaptexture = false;
11803 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11806 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)
11808 static msurface_t surface;
11809 const msurface_t *surfacelist = &surface;
11811 // fake enough texture and surface state to render this geometry
11812 surface.texture = texture;
11813 surface.num_triangles = numtriangles;
11814 surface.num_firsttriangle = firsttriangle;
11815 surface.num_vertices = numvertices;
11816 surface.num_firstvertex = firstvertex;
11819 rsurface.texture = R_GetCurrentTexture(surface.texture);
11820 rsurface.lightmaptexture = NULL;
11821 rsurface.deluxemaptexture = NULL;
11822 rsurface.uselightmaptexture = false;
11823 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);