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_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
176 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)"};
177 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
178 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"};
179 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
180 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
181 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
182 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"};
184 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
185 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
186 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
187 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
189 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
190 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
191 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
192 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
193 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
194 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
195 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
197 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
198 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
199 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
200 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)"};
201 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
202 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
203 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
204 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
205 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
206 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
207 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
209 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"};
211 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"};
213 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
215 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
217 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
218 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"};
220 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."};
222 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)"};
224 extern cvar_t v_glslgamma;
225 extern cvar_t v_glslgamma_2d;
227 extern qboolean v_flipped_state;
229 static struct r_bloomstate_s
234 int bloomwidth, bloomheight;
236 textype_t texturetype;
237 int viewfbo; // used to check if r_viewfbo cvar has changed
239 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
240 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
241 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
243 int screentexturewidth, screentextureheight;
244 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
246 int bloomtexturewidth, bloomtextureheight;
247 rtexture_t *texture_bloom;
249 // arrays for rendering the screen passes
250 float screentexcoord2f[8];
251 float bloomtexcoord2f[8];
252 float offsettexcoord2f[8];
254 r_viewport_t viewport;
258 r_waterstate_t r_waterstate;
260 /// shadow volume bsp struct with automatically growing nodes buffer
263 rtexture_t *r_texture_blanknormalmap;
264 rtexture_t *r_texture_white;
265 rtexture_t *r_texture_grey128;
266 rtexture_t *r_texture_black;
267 rtexture_t *r_texture_notexture;
268 rtexture_t *r_texture_whitecube;
269 rtexture_t *r_texture_normalizationcube;
270 rtexture_t *r_texture_fogattenuation;
271 rtexture_t *r_texture_fogheighttexture;
272 rtexture_t *r_texture_gammaramps;
273 unsigned int r_texture_gammaramps_serial;
274 //rtexture_t *r_texture_fogintensity;
275 rtexture_t *r_texture_reflectcube;
277 // TODO: hash lookups?
278 typedef struct cubemapinfo_s
285 int r_texture_numcubemaps;
286 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
288 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
289 unsigned int r_numqueries;
290 unsigned int r_maxqueries;
292 typedef struct r_qwskincache_s
294 char name[MAX_QPATH];
295 skinframe_t *skinframe;
299 static r_qwskincache_t *r_qwskincache;
300 static int r_qwskincache_size;
302 /// vertex coordinates for a quad that covers the screen exactly
303 extern const float r_screenvertex3f[12];
304 extern const float r_d3dscreenvertex3f[12];
305 const float r_screenvertex3f[12] =
312 const float r_d3dscreenvertex3f[12] =
320 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
323 for (i = 0;i < verts;i++)
334 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
337 for (i = 0;i < verts;i++)
347 // FIXME: move this to client?
350 if (gamemode == GAME_NEHAHRA)
352 Cvar_Set("gl_fogenable", "0");
353 Cvar_Set("gl_fogdensity", "0.2");
354 Cvar_Set("gl_fogred", "0.3");
355 Cvar_Set("gl_foggreen", "0.3");
356 Cvar_Set("gl_fogblue", "0.3");
358 r_refdef.fog_density = 0;
359 r_refdef.fog_red = 0;
360 r_refdef.fog_green = 0;
361 r_refdef.fog_blue = 0;
362 r_refdef.fog_alpha = 1;
363 r_refdef.fog_start = 0;
364 r_refdef.fog_end = 16384;
365 r_refdef.fog_height = 1<<30;
366 r_refdef.fog_fadedepth = 128;
367 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
370 static void R_BuildBlankTextures(void)
372 unsigned char data[4];
373 data[2] = 128; // normal X
374 data[1] = 128; // normal Y
375 data[0] = 255; // normal Z
376 data[3] = 128; // height
377 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
395 static void R_BuildNoTexture(void)
398 unsigned char pix[16][16][4];
399 // this makes a light grey/dark grey checkerboard texture
400 for (y = 0;y < 16;y++)
402 for (x = 0;x < 16;x++)
404 if ((y < 8) ^ (x < 8))
420 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
423 static void R_BuildWhiteCube(void)
425 unsigned char data[6*1*1*4];
426 memset(data, 255, sizeof(data));
427 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
430 static void R_BuildNormalizationCube(void)
434 vec_t s, t, intensity;
437 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
438 for (side = 0;side < 6;side++)
440 for (y = 0;y < NORMSIZE;y++)
442 for (x = 0;x < NORMSIZE;x++)
444 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
480 intensity = 127.0f / sqrt(DotProduct(v, v));
481 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
482 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
483 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
484 data[((side*64+y)*64+x)*4+3] = 255;
488 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
492 static void R_BuildFogTexture(void)
496 unsigned char data1[FOGWIDTH][4];
497 //unsigned char data2[FOGWIDTH][4];
500 r_refdef.fogmasktable_start = r_refdef.fog_start;
501 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
502 r_refdef.fogmasktable_range = r_refdef.fogrange;
503 r_refdef.fogmasktable_density = r_refdef.fog_density;
505 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
506 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
508 d = (x * r - r_refdef.fogmasktable_start);
509 if(developer_extra.integer)
510 Con_DPrintf("%f ", d);
512 if (r_fog_exp2.integer)
513 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
515 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
516 if(developer_extra.integer)
517 Con_DPrintf(" : %f ", alpha);
518 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
519 if(developer_extra.integer)
520 Con_DPrintf(" = %f\n", alpha);
521 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
524 for (x = 0;x < FOGWIDTH;x++)
526 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
531 //data2[x][0] = 255 - b;
532 //data2[x][1] = 255 - b;
533 //data2[x][2] = 255 - b;
536 if (r_texture_fogattenuation)
538 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
543 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
544 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
548 static void R_BuildFogHeightTexture(void)
550 unsigned char *inpixels;
558 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
559 if (r_refdef.fogheighttexturename[0])
560 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
563 r_refdef.fog_height_tablesize = 0;
564 if (r_texture_fogheighttexture)
565 R_FreeTexture(r_texture_fogheighttexture);
566 r_texture_fogheighttexture = NULL;
567 if (r_refdef.fog_height_table2d)
568 Mem_Free(r_refdef.fog_height_table2d);
569 r_refdef.fog_height_table2d = NULL;
570 if (r_refdef.fog_height_table1d)
571 Mem_Free(r_refdef.fog_height_table1d);
572 r_refdef.fog_height_table1d = NULL;
576 r_refdef.fog_height_tablesize = size;
577 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
578 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
579 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
581 // LordHavoc: now the magic - what is that table2d for? it is a cooked
582 // average fog color table accounting for every fog layer between a point
583 // and the camera. (Note: attenuation is handled separately!)
584 for (y = 0;y < size;y++)
586 for (x = 0;x < size;x++)
592 for (j = x;j <= y;j++)
594 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
600 for (j = x;j >= y;j--)
602 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
607 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
608 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
609 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
610 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
613 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
616 //=======================================================================================================================================================
618 static const char *builtinshaderstring =
619 #include "shader_glsl.h"
622 const char *builtinhlslshaderstring =
623 #include "shader_hlsl.h"
626 char *glslshaderstring = NULL;
627 char *hlslshaderstring = NULL;
629 //=======================================================================================================================================================
631 typedef struct shaderpermutationinfo_s
636 shaderpermutationinfo_t;
638 typedef struct shadermodeinfo_s
640 const char *vertexfilename;
641 const char *geometryfilename;
642 const char *fragmentfilename;
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {"#define USEDIFFUSE\n", " diffuse"},
652 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653 {"#define USEVIEWTINT\n", " viewtint"},
654 {"#define USECOLORMAPPING\n", " colormapping"},
655 {"#define USESATURATION\n", " saturation"},
656 {"#define USEFOGINSIDE\n", " foginside"},
657 {"#define USEFOGOUTSIDE\n", " fogoutside"},
658 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660 {"#define USEGAMMARAMPS\n", " gammaramps"},
661 {"#define USECUBEFILTER\n", " cubefilter"},
662 {"#define USEGLOW\n", " glow"},
663 {"#define USEBLOOM\n", " bloom"},
664 {"#define USESPECULAR\n", " specular"},
665 {"#define USEPOSTPROCESSING\n", " postprocessing"},
666 {"#define USEREFLECTION\n", " reflection"},
667 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
671 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
672 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
673 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
674 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
675 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
676 {"#define USEALPHAKILL\n", " alphakill"},
677 {"#define USEREFLECTCUBE\n", " reflectcube"},
678 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
679 {"#define USEBOUNCEGRID\n", " bouncegrid"},
680 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
681 {"#define USETRIPPY\n", " trippy"},
684 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
685 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
704 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
707 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
718 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
719 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
723 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
724 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
725 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
726 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
729 struct r_glsl_permutation_s;
730 typedef struct r_glsl_permutation_s
733 struct r_glsl_permutation_s *hashnext;
735 unsigned int permutation;
737 /// indicates if we have tried compiling this permutation already
739 /// 0 if compilation failed
741 // texture units assigned to each detected uniform
742 int tex_Texture_First;
743 int tex_Texture_Second;
744 int tex_Texture_GammaRamps;
745 int tex_Texture_Normal;
746 int tex_Texture_Color;
747 int tex_Texture_Gloss;
748 int tex_Texture_Glow;
749 int tex_Texture_SecondaryNormal;
750 int tex_Texture_SecondaryColor;
751 int tex_Texture_SecondaryGloss;
752 int tex_Texture_SecondaryGlow;
753 int tex_Texture_Pants;
754 int tex_Texture_Shirt;
755 int tex_Texture_FogHeightTexture;
756 int tex_Texture_FogMask;
757 int tex_Texture_Lightmap;
758 int tex_Texture_Deluxemap;
759 int tex_Texture_Attenuation;
760 int tex_Texture_Cube;
761 int tex_Texture_Refraction;
762 int tex_Texture_Reflection;
763 int tex_Texture_ShadowMap2D;
764 int tex_Texture_CubeProjection;
765 int tex_Texture_ScreenDepth;
766 int tex_Texture_ScreenNormalMap;
767 int tex_Texture_ScreenDiffuse;
768 int tex_Texture_ScreenSpecular;
769 int tex_Texture_ReflectMask;
770 int tex_Texture_ReflectCube;
771 int tex_Texture_BounceGrid;
772 /// locations of detected uniforms in program object, or -1 if not found
773 int loc_Texture_First;
774 int loc_Texture_Second;
775 int loc_Texture_GammaRamps;
776 int loc_Texture_Normal;
777 int loc_Texture_Color;
778 int loc_Texture_Gloss;
779 int loc_Texture_Glow;
780 int loc_Texture_SecondaryNormal;
781 int loc_Texture_SecondaryColor;
782 int loc_Texture_SecondaryGloss;
783 int loc_Texture_SecondaryGlow;
784 int loc_Texture_Pants;
785 int loc_Texture_Shirt;
786 int loc_Texture_FogHeightTexture;
787 int loc_Texture_FogMask;
788 int loc_Texture_Lightmap;
789 int loc_Texture_Deluxemap;
790 int loc_Texture_Attenuation;
791 int loc_Texture_Cube;
792 int loc_Texture_Refraction;
793 int loc_Texture_Reflection;
794 int loc_Texture_ShadowMap2D;
795 int loc_Texture_CubeProjection;
796 int loc_Texture_ScreenDepth;
797 int loc_Texture_ScreenNormalMap;
798 int loc_Texture_ScreenDiffuse;
799 int loc_Texture_ScreenSpecular;
800 int loc_Texture_ReflectMask;
801 int loc_Texture_ReflectCube;
802 int loc_Texture_BounceGrid;
804 int loc_BloomBlur_Parameters;
806 int loc_Color_Ambient;
807 int loc_Color_Diffuse;
808 int loc_Color_Specular;
812 int loc_DeferredColor_Ambient;
813 int loc_DeferredColor_Diffuse;
814 int loc_DeferredColor_Specular;
815 int loc_DeferredMod_Diffuse;
816 int loc_DeferredMod_Specular;
817 int loc_DistortScaleRefractReflect;
820 int loc_FogHeightFade;
822 int loc_FogPlaneViewDist;
823 int loc_FogRangeRecip;
826 int loc_LightPosition;
827 int loc_OffsetMapping_ScaleSteps;
829 int loc_ReflectColor;
830 int loc_ReflectFactor;
831 int loc_ReflectOffset;
832 int loc_RefractColor;
834 int loc_ScreenCenterRefractReflect;
835 int loc_ScreenScaleRefractReflect;
836 int loc_ScreenToDepth;
837 int loc_ShadowMap_Parameters;
838 int loc_ShadowMap_TextureScale;
839 int loc_SpecularPower;
844 int loc_ViewTintColor;
846 int loc_ModelToLight;
848 int loc_BackgroundTexMatrix;
849 int loc_ModelViewProjectionMatrix;
850 int loc_ModelViewMatrix;
851 int loc_PixelToScreenTexCoord;
852 int loc_ModelToReflectCube;
853 int loc_ShadowMapMatrix;
854 int loc_BloomColorSubtract;
855 int loc_NormalmapScrollBlend;
856 int loc_BounceGridMatrix;
857 int loc_BounceGridIntensity;
859 r_glsl_permutation_t;
861 #define SHADERPERMUTATION_HASHSIZE 256
864 // non-degradable "lightweight" shader parameters to keep the permutations simpler
865 // these can NOT degrade! only use for simple stuff
868 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
869 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
870 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
871 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
872 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
873 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
874 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
876 #define SHADERSTATICPARMS_COUNT 7
878 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
879 static int shaderstaticparms_count = 0;
881 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
882 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
883 qboolean R_CompileShader_CheckStaticParms(void)
885 static int r_compileshader_staticparms_save[1];
886 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
887 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
890 if (r_glsl_saturation_redcompensate.integer)
891 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
892 if (r_glsl_vertextextureblend_usebothalphas.integer)
893 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
894 if (r_shadow_glossexact.integer)
895 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
896 if (r_glsl_postprocess.integer)
898 if (r_glsl_postprocess_uservec1_enable.integer)
899 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
900 if (r_glsl_postprocess_uservec2_enable.integer)
901 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
902 if (r_glsl_postprocess_uservec3_enable.integer)
903 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
904 if (r_glsl_postprocess_uservec4_enable.integer)
905 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
907 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
910 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
911 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
912 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
914 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
915 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
917 shaderstaticparms_count = 0;
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
921 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
922 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
923 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
924 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
925 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
926 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
929 /// information about each possible shader permutation
930 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
931 /// currently selected permutation
932 r_glsl_permutation_t *r_glsl_permutation;
933 /// storage for permutations linked in the hash table
934 memexpandablearray_t r_glsl_permutationarray;
936 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
938 //unsigned int hashdepth = 0;
939 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
940 r_glsl_permutation_t *p;
941 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
943 if (p->mode == mode && p->permutation == permutation)
945 //if (hashdepth > 10)
946 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
951 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
953 p->permutation = permutation;
954 p->hashnext = r_glsl_permutationhash[mode][hashindex];
955 r_glsl_permutationhash[mode][hashindex] = p;
956 //if (hashdepth > 10)
957 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
961 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
964 if (!filename || !filename[0])
966 if (!strcmp(filename, "glsl/default.glsl"))
968 if (!glslshaderstring)
970 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
971 if (glslshaderstring)
972 Con_DPrintf("Loading shaders from file %s...\n", filename);
974 glslshaderstring = (char *)builtinshaderstring;
976 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
977 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
980 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
983 if (printfromdisknotice)
984 Con_DPrintf("from disk %s... ", filename);
990 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
994 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
995 char *vertexstring, *geometrystring, *fragmentstring;
996 char permutationname[256];
997 int vertstrings_count = 0;
998 int geomstrings_count = 0;
999 int fragstrings_count = 0;
1000 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1001 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1009 permutationname[0] = 0;
1010 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1011 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1012 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1014 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1016 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1017 if(vid.support.gl20shaders130)
1019 vertstrings_list[vertstrings_count++] = "#version 130\n";
1020 geomstrings_list[geomstrings_count++] = "#version 130\n";
1021 fragstrings_list[fragstrings_count++] = "#version 130\n";
1022 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1023 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1024 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1027 // the first pretext is which type of shader to compile as
1028 // (later these will all be bound together as a program object)
1029 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1030 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1031 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1033 // the second pretext is the mode (for example a light source)
1034 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1035 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1036 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1037 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1039 // now add all the permutation pretexts
1040 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1042 if (permutation & (1<<i))
1044 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1045 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1046 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1047 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1051 // keep line numbers correct
1052 vertstrings_list[vertstrings_count++] = "\n";
1053 geomstrings_list[geomstrings_count++] = "\n";
1054 fragstrings_list[fragstrings_count++] = "\n";
1059 R_CompileShader_AddStaticParms(mode, permutation);
1060 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1061 vertstrings_count += shaderstaticparms_count;
1062 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1063 geomstrings_count += shaderstaticparms_count;
1064 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1065 fragstrings_count += shaderstaticparms_count;
1067 // now append the shader text itself
1068 vertstrings_list[vertstrings_count++] = vertexstring;
1069 geomstrings_list[geomstrings_count++] = geometrystring;
1070 fragstrings_list[fragstrings_count++] = fragmentstring;
1072 // if any sources were NULL, clear the respective list
1074 vertstrings_count = 0;
1075 if (!geometrystring)
1076 geomstrings_count = 0;
1077 if (!fragmentstring)
1078 fragstrings_count = 0;
1080 // compile the shader program
1081 if (vertstrings_count + geomstrings_count + fragstrings_count)
1082 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1086 qglUseProgram(p->program);CHECKGLERROR
1087 // look up all the uniform variable names we care about, so we don't
1088 // have to look them up every time we set them
1090 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1091 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1092 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1093 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1094 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1095 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1096 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1097 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1098 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1099 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1100 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1101 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1102 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1103 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1104 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1105 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1106 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1107 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1108 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1109 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1110 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1111 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1112 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1113 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1114 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1115 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1116 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1117 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1118 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1119 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1120 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1121 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1122 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1123 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1124 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1125 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1126 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1127 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1128 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1129 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1130 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1131 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1132 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1133 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1134 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1135 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1136 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1137 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1138 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1139 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1140 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1141 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1142 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1143 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1144 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1145 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1146 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1147 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1148 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1149 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1150 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1151 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1152 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1153 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1154 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1155 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1156 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1157 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1158 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1159 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1160 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1161 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1162 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1163 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1164 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1165 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1166 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1167 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1168 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1169 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1170 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1171 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1172 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1173 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1174 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1175 // initialize the samplers to refer to the texture units we use
1176 p->tex_Texture_First = -1;
1177 p->tex_Texture_Second = -1;
1178 p->tex_Texture_GammaRamps = -1;
1179 p->tex_Texture_Normal = -1;
1180 p->tex_Texture_Color = -1;
1181 p->tex_Texture_Gloss = -1;
1182 p->tex_Texture_Glow = -1;
1183 p->tex_Texture_SecondaryNormal = -1;
1184 p->tex_Texture_SecondaryColor = -1;
1185 p->tex_Texture_SecondaryGloss = -1;
1186 p->tex_Texture_SecondaryGlow = -1;
1187 p->tex_Texture_Pants = -1;
1188 p->tex_Texture_Shirt = -1;
1189 p->tex_Texture_FogHeightTexture = -1;
1190 p->tex_Texture_FogMask = -1;
1191 p->tex_Texture_Lightmap = -1;
1192 p->tex_Texture_Deluxemap = -1;
1193 p->tex_Texture_Attenuation = -1;
1194 p->tex_Texture_Cube = -1;
1195 p->tex_Texture_Refraction = -1;
1196 p->tex_Texture_Reflection = -1;
1197 p->tex_Texture_ShadowMap2D = -1;
1198 p->tex_Texture_CubeProjection = -1;
1199 p->tex_Texture_ScreenDepth = -1;
1200 p->tex_Texture_ScreenNormalMap = -1;
1201 p->tex_Texture_ScreenDiffuse = -1;
1202 p->tex_Texture_ScreenSpecular = -1;
1203 p->tex_Texture_ReflectMask = -1;
1204 p->tex_Texture_ReflectCube = -1;
1205 p->tex_Texture_BounceGrid = -1;
1207 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1208 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1209 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1210 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1211 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1212 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1213 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1214 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1215 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1216 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1217 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1218 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1219 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1220 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1221 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1222 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1223 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1224 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1225 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1226 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1227 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1228 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1229 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1230 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1231 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1232 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1233 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1234 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1235 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1236 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1238 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1241 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1245 Mem_Free(vertexstring);
1247 Mem_Free(geometrystring);
1249 Mem_Free(fragmentstring);
1252 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1254 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1255 if (r_glsl_permutation != perm)
1257 r_glsl_permutation = perm;
1258 if (!r_glsl_permutation->program)
1260 if (!r_glsl_permutation->compiled)
1261 R_GLSL_CompilePermutation(perm, mode, permutation);
1262 if (!r_glsl_permutation->program)
1264 // remove features until we find a valid permutation
1266 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1268 // reduce i more quickly whenever it would not remove any bits
1269 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1270 if (!(permutation & j))
1273 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1274 if (!r_glsl_permutation->compiled)
1275 R_GLSL_CompilePermutation(perm, mode, permutation);
1276 if (r_glsl_permutation->program)
1279 if (i >= SHADERPERMUTATION_COUNT)
1281 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1282 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1283 qglUseProgram(0);CHECKGLERROR
1284 return; // no bit left to clear, entire mode is broken
1289 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1291 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1292 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1293 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1300 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1301 extern D3DCAPS9 vid_d3d9caps;
1304 struct r_hlsl_permutation_s;
1305 typedef struct r_hlsl_permutation_s
1307 /// hash lookup data
1308 struct r_hlsl_permutation_s *hashnext;
1310 unsigned int permutation;
1312 /// indicates if we have tried compiling this permutation already
1314 /// NULL if compilation failed
1315 IDirect3DVertexShader9 *vertexshader;
1316 IDirect3DPixelShader9 *pixelshader;
1318 r_hlsl_permutation_t;
1320 typedef enum D3DVSREGISTER_e
1322 D3DVSREGISTER_TexMatrix = 0, // float4x4
1323 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1324 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1325 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1326 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1327 D3DVSREGISTER_ModelToLight = 20, // float4x4
1328 D3DVSREGISTER_EyePosition = 24,
1329 D3DVSREGISTER_FogPlane = 25,
1330 D3DVSREGISTER_LightDir = 26,
1331 D3DVSREGISTER_LightPosition = 27,
1335 typedef enum D3DPSREGISTER_e
1337 D3DPSREGISTER_Alpha = 0,
1338 D3DPSREGISTER_BloomBlur_Parameters = 1,
1339 D3DPSREGISTER_ClientTime = 2,
1340 D3DPSREGISTER_Color_Ambient = 3,
1341 D3DPSREGISTER_Color_Diffuse = 4,
1342 D3DPSREGISTER_Color_Specular = 5,
1343 D3DPSREGISTER_Color_Glow = 6,
1344 D3DPSREGISTER_Color_Pants = 7,
1345 D3DPSREGISTER_Color_Shirt = 8,
1346 D3DPSREGISTER_DeferredColor_Ambient = 9,
1347 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1348 D3DPSREGISTER_DeferredColor_Specular = 11,
1349 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1350 D3DPSREGISTER_DeferredMod_Specular = 13,
1351 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1352 D3DPSREGISTER_EyePosition = 15, // unused
1353 D3DPSREGISTER_FogColor = 16,
1354 D3DPSREGISTER_FogHeightFade = 17,
1355 D3DPSREGISTER_FogPlane = 18,
1356 D3DPSREGISTER_FogPlaneViewDist = 19,
1357 D3DPSREGISTER_FogRangeRecip = 20,
1358 D3DPSREGISTER_LightColor = 21,
1359 D3DPSREGISTER_LightDir = 22, // unused
1360 D3DPSREGISTER_LightPosition = 23,
1361 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1362 D3DPSREGISTER_PixelSize = 25,
1363 D3DPSREGISTER_ReflectColor = 26,
1364 D3DPSREGISTER_ReflectFactor = 27,
1365 D3DPSREGISTER_ReflectOffset = 28,
1366 D3DPSREGISTER_RefractColor = 29,
1367 D3DPSREGISTER_Saturation = 30,
1368 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1369 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1370 D3DPSREGISTER_ScreenToDepth = 33,
1371 D3DPSREGISTER_ShadowMap_Parameters = 34,
1372 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1373 D3DPSREGISTER_SpecularPower = 36,
1374 D3DPSREGISTER_UserVec1 = 37,
1375 D3DPSREGISTER_UserVec2 = 38,
1376 D3DPSREGISTER_UserVec3 = 39,
1377 D3DPSREGISTER_UserVec4 = 40,
1378 D3DPSREGISTER_ViewTintColor = 41,
1379 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1380 D3DPSREGISTER_BloomColorSubtract = 43,
1381 D3DPSREGISTER_ViewToLight = 44, // float4x4
1382 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1383 D3DPSREGISTER_NormalmapScrollBlend = 52,
1388 /// information about each possible shader permutation
1389 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1390 /// currently selected permutation
1391 r_hlsl_permutation_t *r_hlsl_permutation;
1392 /// storage for permutations linked in the hash table
1393 memexpandablearray_t r_hlsl_permutationarray;
1395 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1397 //unsigned int hashdepth = 0;
1398 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1399 r_hlsl_permutation_t *p;
1400 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1402 if (p->mode == mode && p->permutation == permutation)
1404 //if (hashdepth > 10)
1405 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1410 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1412 p->permutation = permutation;
1413 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1414 r_hlsl_permutationhash[mode][hashindex] = p;
1415 //if (hashdepth > 10)
1416 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1420 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1423 if (!filename || !filename[0])
1425 if (!strcmp(filename, "hlsl/default.hlsl"))
1427 if (!hlslshaderstring)
1429 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1430 if (hlslshaderstring)
1431 Con_DPrintf("Loading shaders from file %s...\n", filename);
1433 hlslshaderstring = (char *)builtinhlslshaderstring;
1435 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1436 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1437 return shaderstring;
1439 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1442 if (printfromdisknotice)
1443 Con_DPrintf("from disk %s... ", filename);
1444 return shaderstring;
1446 return shaderstring;
1450 //#include <d3dx9shader.h>
1451 //#include <d3dx9mesh.h>
1453 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1455 DWORD *vsbin = NULL;
1456 DWORD *psbin = NULL;
1457 fs_offset_t vsbinsize;
1458 fs_offset_t psbinsize;
1459 // IDirect3DVertexShader9 *vs = NULL;
1460 // IDirect3DPixelShader9 *ps = NULL;
1461 ID3DXBuffer *vslog = NULL;
1462 ID3DXBuffer *vsbuffer = NULL;
1463 ID3DXConstantTable *vsconstanttable = NULL;
1464 ID3DXBuffer *pslog = NULL;
1465 ID3DXBuffer *psbuffer = NULL;
1466 ID3DXConstantTable *psconstanttable = NULL;
1469 char temp[MAX_INPUTLINE];
1470 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1471 qboolean debugshader = gl_paranoid.integer != 0;
1472 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1473 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1476 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1477 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1479 if ((!vsbin && vertstring) || (!psbin && fragstring))
1481 const char* dllnames_d3dx9 [] =
1505 dllhandle_t d3dx9_dll = NULL;
1506 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1507 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1508 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1509 dllfunction_t d3dx9_dllfuncs[] =
1511 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1512 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1513 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1516 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1518 DWORD shaderflags = 0;
1520 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1521 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1522 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1523 if (vertstring && vertstring[0])
1527 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1528 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1529 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1530 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1533 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1536 vsbinsize = vsbuffer->GetBufferSize();
1537 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1538 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1539 vsbuffer->Release();
1543 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1544 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1548 if (fragstring && fragstring[0])
1552 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1553 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1554 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1555 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1558 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1561 psbinsize = psbuffer->GetBufferSize();
1562 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1563 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1564 psbuffer->Release();
1568 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1569 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1573 Sys_UnloadLibrary(&d3dx9_dll);
1576 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1580 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1581 if (FAILED(vsresult))
1582 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1583 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1584 if (FAILED(psresult))
1585 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1587 // free the shader data
1588 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1589 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1592 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1595 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1596 int vertstring_length = 0;
1597 int geomstring_length = 0;
1598 int fragstring_length = 0;
1600 char *vertexstring, *geometrystring, *fragmentstring;
1601 char *vertstring, *geomstring, *fragstring;
1602 char permutationname[256];
1603 char cachename[256];
1604 int vertstrings_count = 0;
1605 int geomstrings_count = 0;
1606 int fragstrings_count = 0;
1607 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1614 p->vertexshader = NULL;
1615 p->pixelshader = NULL;
1617 permutationname[0] = 0;
1619 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1620 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1621 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1623 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1624 strlcat(cachename, "hlsl/", sizeof(cachename));
1626 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1627 vertstrings_count = 0;
1628 geomstrings_count = 0;
1629 fragstrings_count = 0;
1630 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1631 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1632 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1634 // the first pretext is which type of shader to compile as
1635 // (later these will all be bound together as a program object)
1636 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1637 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1638 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1640 // the second pretext is the mode (for example a light source)
1641 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1642 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1643 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1644 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1645 strlcat(cachename, modeinfo->name, sizeof(cachename));
1647 // now add all the permutation pretexts
1648 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1650 if (permutation & (1<<i))
1652 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1653 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1654 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1655 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1656 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1660 // keep line numbers correct
1661 vertstrings_list[vertstrings_count++] = "\n";
1662 geomstrings_list[geomstrings_count++] = "\n";
1663 fragstrings_list[fragstrings_count++] = "\n";
1668 R_CompileShader_AddStaticParms(mode, permutation);
1669 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1670 vertstrings_count += shaderstaticparms_count;
1671 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1672 geomstrings_count += shaderstaticparms_count;
1673 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1674 fragstrings_count += shaderstaticparms_count;
1676 // replace spaces in the cachename with _ characters
1677 for (i = 0;cachename[i];i++)
1678 if (cachename[i] == ' ')
1681 // now append the shader text itself
1682 vertstrings_list[vertstrings_count++] = vertexstring;
1683 geomstrings_list[geomstrings_count++] = geometrystring;
1684 fragstrings_list[fragstrings_count++] = fragmentstring;
1686 // if any sources were NULL, clear the respective list
1688 vertstrings_count = 0;
1689 if (!geometrystring)
1690 geomstrings_count = 0;
1691 if (!fragmentstring)
1692 fragstrings_count = 0;
1694 vertstring_length = 0;
1695 for (i = 0;i < vertstrings_count;i++)
1696 vertstring_length += strlen(vertstrings_list[i]);
1697 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1698 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1699 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1701 geomstring_length = 0;
1702 for (i = 0;i < geomstrings_count;i++)
1703 geomstring_length += strlen(geomstrings_list[i]);
1704 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1705 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1706 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1708 fragstring_length = 0;
1709 for (i = 0;i < fragstrings_count;i++)
1710 fragstring_length += strlen(fragstrings_list[i]);
1711 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1712 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1713 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1715 // try to load the cached shader, or generate one
1716 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1718 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1719 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1721 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1725 Mem_Free(vertstring);
1727 Mem_Free(geomstring);
1729 Mem_Free(fragstring);
1731 Mem_Free(vertexstring);
1733 Mem_Free(geometrystring);
1735 Mem_Free(fragmentstring);
1738 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 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);}
1741 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);}
1742 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);}
1743 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);}
1745 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1746 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1747 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);}
1748 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);}
1749 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);}
1750 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);}
1752 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1754 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1755 if (r_hlsl_permutation != perm)
1757 r_hlsl_permutation = perm;
1758 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1760 if (!r_hlsl_permutation->compiled)
1761 R_HLSL_CompilePermutation(perm, mode, permutation);
1762 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1764 // remove features until we find a valid permutation
1766 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1768 // reduce i more quickly whenever it would not remove any bits
1769 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1770 if (!(permutation & j))
1773 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1774 if (!r_hlsl_permutation->compiled)
1775 R_HLSL_CompilePermutation(perm, mode, permutation);
1776 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1779 if (i >= SHADERPERMUTATION_COUNT)
1781 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1782 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1783 return; // no bit left to clear, entire mode is broken
1787 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1788 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1790 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1791 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1792 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1796 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1798 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1799 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1800 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1801 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1804 void R_GLSL_Restart_f(void)
1806 unsigned int i, limit;
1807 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1808 Mem_Free(glslshaderstring);
1809 glslshaderstring = NULL;
1810 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1811 Mem_Free(hlslshaderstring);
1812 hlslshaderstring = NULL;
1813 switch(vid.renderpath)
1815 case RENDERPATH_D3D9:
1818 r_hlsl_permutation_t *p;
1819 r_hlsl_permutation = NULL;
1820 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1821 for (i = 0;i < limit;i++)
1823 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1825 if (p->vertexshader)
1826 IDirect3DVertexShader9_Release(p->vertexshader);
1828 IDirect3DPixelShader9_Release(p->pixelshader);
1829 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1832 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1836 case RENDERPATH_D3D10:
1837 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1839 case RENDERPATH_D3D11:
1840 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1842 case RENDERPATH_GL20:
1843 case RENDERPATH_GLES2:
1845 r_glsl_permutation_t *p;
1846 r_glsl_permutation = NULL;
1847 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1848 for (i = 0;i < limit;i++)
1850 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1852 GL_Backend_FreeProgram(p->program);
1853 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1856 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1859 case RENDERPATH_GL11:
1860 case RENDERPATH_GL13:
1861 case RENDERPATH_GLES1:
1863 case RENDERPATH_SOFT:
1868 void R_GLSL_DumpShader_f(void)
1873 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1876 FS_Print(file, "/* The engine may define the following macros:\n");
1877 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1878 for (i = 0;i < SHADERMODE_COUNT;i++)
1879 FS_Print(file, glslshadermodeinfo[i].pretext);
1880 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1881 FS_Print(file, shaderpermutationinfo[i].pretext);
1882 FS_Print(file, "*/\n");
1883 FS_Print(file, builtinshaderstring);
1885 Con_Printf("glsl/default.glsl written\n");
1888 Con_Printf("failed to write to glsl/default.glsl\n");
1890 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1893 FS_Print(file, "/* The engine may define the following macros:\n");
1894 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1895 for (i = 0;i < SHADERMODE_COUNT;i++)
1896 FS_Print(file, hlslshadermodeinfo[i].pretext);
1897 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1898 FS_Print(file, shaderpermutationinfo[i].pretext);
1899 FS_Print(file, "*/\n");
1900 FS_Print(file, builtinhlslshaderstring);
1902 Con_Printf("hlsl/default.hlsl written\n");
1905 Con_Printf("failed to write to hlsl/default.hlsl\n");
1908 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1910 unsigned int permutation = 0;
1911 if (r_trippy.integer && !notrippy)
1912 permutation |= SHADERPERMUTATION_TRIPPY;
1913 permutation |= SHADERPERMUTATION_VIEWTINT;
1915 permutation |= SHADERPERMUTATION_DIFFUSE;
1917 permutation |= SHADERPERMUTATION_SPECULAR;
1918 if (texturemode == GL_MODULATE)
1919 permutation |= SHADERPERMUTATION_COLORMAPPING;
1920 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1921 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1922 else if (texturemode == GL_ADD)
1923 permutation |= SHADERPERMUTATION_GLOW;
1924 else if (texturemode == GL_DECAL)
1925 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1927 texturemode = GL_MODULATE;
1928 if (vid.allowalphatocoverage)
1929 GL_AlphaToCoverage(false);
1930 switch (vid.renderpath)
1932 case RENDERPATH_D3D9:
1934 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1935 R_Mesh_TexBind(GL20TU_FIRST , first );
1936 R_Mesh_TexBind(GL20TU_SECOND, second);
1937 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1938 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1941 case RENDERPATH_D3D10:
1942 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944 case RENDERPATH_D3D11:
1945 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1947 case RENDERPATH_GL20:
1948 case RENDERPATH_GLES2:
1949 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1950 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1951 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1952 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1953 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1955 case RENDERPATH_GL13:
1956 case RENDERPATH_GLES1:
1957 R_Mesh_TexBind(0, first );
1958 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1959 R_Mesh_TexBind(1, second);
1961 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1963 case RENDERPATH_GL11:
1964 R_Mesh_TexBind(0, first );
1966 case RENDERPATH_SOFT:
1967 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1968 R_Mesh_TexBind(GL20TU_FIRST , first );
1969 R_Mesh_TexBind(GL20TU_SECOND, second);
1974 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1976 unsigned int permutation = 0;
1977 if (r_trippy.integer && !notrippy)
1978 permutation |= SHADERPERMUTATION_TRIPPY;
1979 if (vid.allowalphatocoverage)
1980 GL_AlphaToCoverage(false);
1981 switch (vid.renderpath)
1983 case RENDERPATH_D3D9:
1985 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1988 case RENDERPATH_D3D10:
1989 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1991 case RENDERPATH_D3D11:
1992 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1994 case RENDERPATH_GL20:
1995 case RENDERPATH_GLES2:
1996 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1998 case RENDERPATH_GL13:
1999 case RENDERPATH_GLES1:
2000 R_Mesh_TexBind(0, 0);
2001 R_Mesh_TexBind(1, 0);
2003 case RENDERPATH_GL11:
2004 R_Mesh_TexBind(0, 0);
2006 case RENDERPATH_SOFT:
2007 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2012 void R_SetupShader_ShowDepth(qboolean notrippy)
2014 int permutation = 0;
2015 if (r_trippy.integer && !notrippy)
2016 permutation |= SHADERPERMUTATION_TRIPPY;
2017 if (vid.allowalphatocoverage)
2018 GL_AlphaToCoverage(false);
2019 switch (vid.renderpath)
2021 case RENDERPATH_D3D9:
2023 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2026 case RENDERPATH_D3D10:
2027 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2029 case RENDERPATH_D3D11:
2030 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2032 case RENDERPATH_GL20:
2033 case RENDERPATH_GLES2:
2034 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2036 case RENDERPATH_GL13:
2037 case RENDERPATH_GLES1:
2039 case RENDERPATH_GL11:
2041 case RENDERPATH_SOFT:
2042 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2047 extern qboolean r_shadow_usingdeferredprepass;
2048 extern cvar_t r_shadow_deferred_8bitrange;
2049 extern rtexture_t *r_shadow_attenuationgradienttexture;
2050 extern rtexture_t *r_shadow_attenuation2dtexture;
2051 extern rtexture_t *r_shadow_attenuation3dtexture;
2052 extern qboolean r_shadow_usingshadowmap2d;
2053 extern qboolean r_shadow_usingshadowmaportho;
2054 extern float r_shadow_shadowmap_texturescale[2];
2055 extern float r_shadow_shadowmap_parameters[4];
2056 extern qboolean r_shadow_shadowmapvsdct;
2057 extern qboolean r_shadow_shadowmapsampler;
2058 extern int r_shadow_shadowmappcf;
2059 extern rtexture_t *r_shadow_shadowmap2dtexture;
2060 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2061 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2062 extern matrix4x4_t r_shadow_shadowmapmatrix;
2063 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2064 extern int r_shadow_prepass_width;
2065 extern int r_shadow_prepass_height;
2066 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2067 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2068 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2069 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2070 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2072 #define BLENDFUNC_ALLOWS_COLORMOD 1
2073 #define BLENDFUNC_ALLOWS_FOG 2
2074 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2075 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2076 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2077 static int R_BlendFuncFlags(int src, int dst)
2081 // a blendfunc allows colormod if:
2082 // a) it can never keep the destination pixel invariant, or
2083 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2084 // this is to prevent unintended side effects from colormod
2086 // a blendfunc allows fog if:
2087 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2088 // this is to prevent unintended side effects from fog
2090 // these checks are the output of fogeval.pl
2092 r |= BLENDFUNC_ALLOWS_COLORMOD;
2093 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2095 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2096 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2097 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2100 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2101 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2102 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2103 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2104 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2106 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2107 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2108 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2110 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2111 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2112 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2113 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2118 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)
2120 // select a permutation of the lighting shader appropriate to this
2121 // combination of texture, entity, light source, and fogging, only use the
2122 // minimum features necessary to avoid wasting rendering time in the
2123 // fragment shader on features that are not being used
2124 unsigned int permutation = 0;
2125 unsigned int mode = 0;
2127 static float dummy_colormod[3] = {1, 1, 1};
2128 float *colormod = rsurface.colormod;
2130 matrix4x4_t tempmatrix;
2131 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2132 if (r_trippy.integer && !notrippy)
2133 permutation |= SHADERPERMUTATION_TRIPPY;
2134 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2135 permutation |= SHADERPERMUTATION_ALPHAKILL;
2136 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2137 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2138 if (rsurfacepass == RSURFPASS_BACKGROUND)
2140 // distorted background
2141 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2143 mode = SHADERMODE_WATER;
2144 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2146 // this is the right thing to do for wateralpha
2147 GL_BlendFunc(GL_ONE, GL_ZERO);
2148 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2152 // this is the right thing to do for entity alpha
2153 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2157 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2159 mode = SHADERMODE_REFRACTION;
2160 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2161 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2165 mode = SHADERMODE_GENERIC;
2166 permutation |= SHADERPERMUTATION_DIFFUSE;
2167 GL_BlendFunc(GL_ONE, GL_ZERO);
2168 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2170 if (vid.allowalphatocoverage)
2171 GL_AlphaToCoverage(false);
2173 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2175 if (r_glsl_offsetmapping.integer)
2177 switch(rsurface.texture->offsetmapping)
2179 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2180 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2181 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2182 case OFFSETMAPPING_OFF: break;
2185 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2186 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2187 // normalmap (deferred prepass), may use alpha test on diffuse
2188 mode = SHADERMODE_DEFERREDGEOMETRY;
2189 GL_BlendFunc(GL_ONE, GL_ZERO);
2190 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2191 if (vid.allowalphatocoverage)
2192 GL_AlphaToCoverage(false);
2194 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2196 if (r_glsl_offsetmapping.integer)
2198 switch(rsurface.texture->offsetmapping)
2200 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2201 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2203 case OFFSETMAPPING_OFF: break;
2206 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2207 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2209 mode = SHADERMODE_LIGHTSOURCE;
2210 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2211 permutation |= SHADERPERMUTATION_CUBEFILTER;
2212 if (diffusescale > 0)
2213 permutation |= SHADERPERMUTATION_DIFFUSE;
2214 if (specularscale > 0)
2215 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2216 if (r_refdef.fogenabled)
2217 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2218 if (rsurface.texture->colormapping)
2219 permutation |= SHADERPERMUTATION_COLORMAPPING;
2220 if (r_shadow_usingshadowmap2d)
2222 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2223 if(r_shadow_shadowmapvsdct)
2224 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2226 if (r_shadow_shadowmapsampler)
2227 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2228 if (r_shadow_shadowmappcf > 1)
2229 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2230 else if (r_shadow_shadowmappcf)
2231 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2233 if (rsurface.texture->reflectmasktexture)
2234 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2235 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2236 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2237 if (vid.allowalphatocoverage)
2238 GL_AlphaToCoverage(false);
2240 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2242 if (r_glsl_offsetmapping.integer)
2244 switch(rsurface.texture->offsetmapping)
2246 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2247 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2248 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2249 case OFFSETMAPPING_OFF: break;
2252 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2253 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2254 // unshaded geometry (fullbright or ambient model lighting)
2255 mode = SHADERMODE_FLATCOLOR;
2256 ambientscale = diffusescale = specularscale = 0;
2257 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2258 permutation |= SHADERPERMUTATION_GLOW;
2259 if (r_refdef.fogenabled)
2260 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2261 if (rsurface.texture->colormapping)
2262 permutation |= SHADERPERMUTATION_COLORMAPPING;
2263 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2265 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2266 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2268 if (r_shadow_shadowmapsampler)
2269 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2270 if (r_shadow_shadowmappcf > 1)
2271 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2272 else if (r_shadow_shadowmappcf)
2273 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2275 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2276 permutation |= SHADERPERMUTATION_REFLECTION;
2277 if (rsurface.texture->reflectmasktexture)
2278 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2279 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2280 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2281 // when using alphatocoverage, we don't need alphakill
2282 if (vid.allowalphatocoverage)
2284 if (r_transparent_alphatocoverage.integer)
2286 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2287 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2290 GL_AlphaToCoverage(false);
2293 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2295 if (r_glsl_offsetmapping.integer)
2297 switch(rsurface.texture->offsetmapping)
2299 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2300 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2302 case OFFSETMAPPING_OFF: break;
2305 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2306 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2307 // directional model lighting
2308 mode = SHADERMODE_LIGHTDIRECTION;
2309 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2310 permutation |= SHADERPERMUTATION_GLOW;
2311 permutation |= SHADERPERMUTATION_DIFFUSE;
2312 if (specularscale > 0)
2313 permutation |= SHADERPERMUTATION_SPECULAR;
2314 if (r_refdef.fogenabled)
2315 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2316 if (rsurface.texture->colormapping)
2317 permutation |= SHADERPERMUTATION_COLORMAPPING;
2318 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2320 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2321 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2323 if (r_shadow_shadowmapsampler)
2324 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2325 if (r_shadow_shadowmappcf > 1)
2326 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2327 else if (r_shadow_shadowmappcf)
2328 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2330 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2331 permutation |= SHADERPERMUTATION_REFLECTION;
2332 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2333 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2334 if (rsurface.texture->reflectmasktexture)
2335 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2338 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2339 if (r_shadow_bouncegriddirectional)
2340 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2342 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2344 // when using alphatocoverage, we don't need alphakill
2345 if (vid.allowalphatocoverage)
2347 if (r_transparent_alphatocoverage.integer)
2349 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2350 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2353 GL_AlphaToCoverage(false);
2356 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2358 if (r_glsl_offsetmapping.integer)
2360 switch(rsurface.texture->offsetmapping)
2362 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2363 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2364 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2365 case OFFSETMAPPING_OFF: break;
2368 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2369 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2370 // ambient model lighting
2371 mode = SHADERMODE_LIGHTDIRECTION;
2372 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2373 permutation |= SHADERPERMUTATION_GLOW;
2374 if (r_refdef.fogenabled)
2375 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2376 if (rsurface.texture->colormapping)
2377 permutation |= SHADERPERMUTATION_COLORMAPPING;
2378 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2380 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2381 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2383 if (r_shadow_shadowmapsampler)
2384 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2385 if (r_shadow_shadowmappcf > 1)
2386 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2387 else if (r_shadow_shadowmappcf)
2388 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2390 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2391 permutation |= SHADERPERMUTATION_REFLECTION;
2392 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2393 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2394 if (rsurface.texture->reflectmasktexture)
2395 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2396 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2398 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2399 if (r_shadow_bouncegriddirectional)
2400 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2402 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2403 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2404 // when using alphatocoverage, we don't need alphakill
2405 if (vid.allowalphatocoverage)
2407 if (r_transparent_alphatocoverage.integer)
2409 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2410 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2413 GL_AlphaToCoverage(false);
2418 if (r_glsl_offsetmapping.integer)
2420 switch(rsurface.texture->offsetmapping)
2422 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2423 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2424 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2425 case OFFSETMAPPING_OFF: break;
2428 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2429 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2431 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2432 permutation |= SHADERPERMUTATION_GLOW;
2433 if (r_refdef.fogenabled)
2434 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2435 if (rsurface.texture->colormapping)
2436 permutation |= SHADERPERMUTATION_COLORMAPPING;
2437 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2439 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2440 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2442 if (r_shadow_shadowmapsampler)
2443 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2444 if (r_shadow_shadowmappcf > 1)
2445 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2446 else if (r_shadow_shadowmappcf)
2447 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2449 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2450 permutation |= SHADERPERMUTATION_REFLECTION;
2451 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2452 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2453 if (rsurface.texture->reflectmasktexture)
2454 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2455 if (FAKELIGHT_ENABLED)
2457 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2458 mode = SHADERMODE_FAKELIGHT;
2459 permutation |= SHADERPERMUTATION_DIFFUSE;
2460 if (specularscale > 0)
2461 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2463 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2465 // deluxemapping (light direction texture)
2466 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2467 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2469 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2470 permutation |= SHADERPERMUTATION_DIFFUSE;
2471 if (specularscale > 0)
2472 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2474 else if (r_glsl_deluxemapping.integer >= 2)
2476 // fake deluxemapping (uniform light direction in tangentspace)
2477 if (rsurface.uselightmaptexture)
2478 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2480 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2481 permutation |= SHADERPERMUTATION_DIFFUSE;
2482 if (specularscale > 0)
2483 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2485 else if (rsurface.uselightmaptexture)
2487 // ordinary lightmapping (q1bsp, q3bsp)
2488 mode = SHADERMODE_LIGHTMAP;
2492 // ordinary vertex coloring (q3bsp)
2493 mode = SHADERMODE_VERTEXCOLOR;
2495 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2497 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2498 if (r_shadow_bouncegriddirectional)
2499 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2501 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2502 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2503 // when using alphatocoverage, we don't need alphakill
2504 if (vid.allowalphatocoverage)
2506 if (r_transparent_alphatocoverage.integer)
2508 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2509 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2512 GL_AlphaToCoverage(false);
2515 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2516 colormod = dummy_colormod;
2517 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2518 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2519 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2520 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2521 switch(vid.renderpath)
2523 case RENDERPATH_D3D9:
2525 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);
2526 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2527 R_SetupShader_SetPermutationHLSL(mode, permutation);
2528 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2529 if (mode == SHADERMODE_LIGHTSOURCE)
2531 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2532 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2536 if (mode == SHADERMODE_LIGHTDIRECTION)
2538 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2541 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2542 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2543 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2544 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2545 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2547 if (mode == SHADERMODE_LIGHTSOURCE)
2549 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2550 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2551 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2552 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2553 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2555 // additive passes are only darkened by fog, not tinted
2556 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2557 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2561 if (mode == SHADERMODE_FLATCOLOR)
2563 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2565 else if (mode == SHADERMODE_LIGHTDIRECTION)
2567 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]);
2568 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2569 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);
2570 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);
2571 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2572 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2573 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2577 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2578 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2579 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);
2580 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);
2581 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2583 // additive passes are only darkened by fog, not tinted
2584 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2585 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2587 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2588 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);
2589 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2590 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2591 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2592 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2593 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2594 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2595 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2596 if (mode == SHADERMODE_WATER)
2597 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2599 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2600 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2601 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2602 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));
2603 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2604 if (rsurface.texture->pantstexture)
2605 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2607 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2608 if (rsurface.texture->shirttexture)
2609 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2611 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2612 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2613 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2614 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2615 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2616 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2617 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2618 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2619 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2620 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2622 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2623 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2625 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2626 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2627 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2628 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2629 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2630 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2631 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2632 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2633 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2634 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2635 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2636 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2637 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2638 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2639 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2640 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2641 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2642 if (rsurfacepass == RSURFPASS_BACKGROUND)
2644 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2645 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2646 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2650 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2652 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2653 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2654 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2655 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2656 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2658 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2659 if (rsurface.rtlight)
2661 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2662 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2667 case RENDERPATH_D3D10:
2668 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2670 case RENDERPATH_D3D11:
2671 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2673 case RENDERPATH_GL20:
2674 case RENDERPATH_GLES2:
2675 if (!vid.useinterleavedarrays)
2677 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);
2678 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2679 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2680 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2681 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2682 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2683 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2684 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2688 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);
2689 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2691 R_SetupShader_SetPermutationGLSL(mode, permutation);
2692 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2693 if (mode == SHADERMODE_LIGHTSOURCE)
2695 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2696 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2697 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2698 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2699 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2700 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);
2702 // additive passes are only darkened by fog, not tinted
2703 if (r_glsl_permutation->loc_FogColor >= 0)
2704 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2705 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2709 if (mode == SHADERMODE_FLATCOLOR)
2711 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2713 else if (mode == SHADERMODE_LIGHTDIRECTION)
2715 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]);
2716 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]);
2717 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);
2718 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);
2719 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);
2720 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]);
2721 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]);
2725 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]);
2726 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]);
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] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * 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);
2731 // additive passes are only darkened by fog, not tinted
2732 if (r_glsl_permutation->loc_FogColor >= 0)
2734 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2735 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2737 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2739 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);
2740 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]);
2741 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]);
2742 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]);
2743 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]);
2744 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2745 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2746 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2747 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]);
2749 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2750 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2751 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2752 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]);
2753 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]);
2755 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2756 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));
2757 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2758 if (r_glsl_permutation->loc_Color_Pants >= 0)
2760 if (rsurface.texture->pantstexture)
2761 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2763 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2765 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2767 if (rsurface.texture->shirttexture)
2768 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2770 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2772 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]);
2773 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2774 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2775 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2776 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2777 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2778 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2779 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2780 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2782 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]);
2783 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2784 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);}
2785 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2787 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2788 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2789 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2790 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2791 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2792 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2793 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2794 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2795 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2796 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2797 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2798 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2799 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2800 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2801 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);
2802 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2803 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2804 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2805 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2806 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2807 if (rsurfacepass == RSURFPASS_BACKGROUND)
2809 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);
2810 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);
2811 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);
2815 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);
2817 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2818 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2819 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2820 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2821 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2823 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2824 if (rsurface.rtlight)
2826 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2827 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2830 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2833 case RENDERPATH_GL11:
2834 case RENDERPATH_GL13:
2835 case RENDERPATH_GLES1:
2837 case RENDERPATH_SOFT:
2838 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);
2839 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2840 R_SetupShader_SetPermutationSoft(mode, permutation);
2841 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2842 if (mode == SHADERMODE_LIGHTSOURCE)
2844 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2845 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2846 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2847 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2848 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2849 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2851 // additive passes are only darkened by fog, not tinted
2852 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2853 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2857 if (mode == SHADERMODE_FLATCOLOR)
2859 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2861 else if (mode == SHADERMODE_LIGHTDIRECTION)
2863 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]);
2864 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2865 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);
2866 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);
2867 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2868 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]);
2869 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2873 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2874 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2875 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2876 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2877 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2879 // additive passes are only darkened by fog, not tinted
2880 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2881 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2883 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2884 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);
2885 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2886 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2887 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]);
2888 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]);
2889 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2890 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2891 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2892 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2894 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2895 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2896 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2897 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2898 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]);
2900 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2901 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));
2902 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2903 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2905 if (rsurface.texture->pantstexture)
2906 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2908 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2910 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2912 if (rsurface.texture->shirttexture)
2913 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2915 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2917 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2918 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2919 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2920 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2921 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2922 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2923 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2924 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2925 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2927 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2928 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2930 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2931 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2932 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2933 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2934 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2935 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2936 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2937 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2938 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2939 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2940 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2941 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2942 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2943 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2944 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2945 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2946 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2947 if (rsurfacepass == RSURFPASS_BACKGROUND)
2949 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2950 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2951 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2955 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2957 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2958 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2959 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2960 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2961 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2963 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2964 if (rsurface.rtlight)
2966 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2967 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2974 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2976 // select a permutation of the lighting shader appropriate to this
2977 // combination of texture, entity, light source, and fogging, only use the
2978 // minimum features necessary to avoid wasting rendering time in the
2979 // fragment shader on features that are not being used
2980 unsigned int permutation = 0;
2981 unsigned int mode = 0;
2982 const float *lightcolorbase = rtlight->currentcolor;
2983 float ambientscale = rtlight->ambientscale;
2984 float diffusescale = rtlight->diffusescale;
2985 float specularscale = rtlight->specularscale;
2986 // this is the location of the light in view space
2987 vec3_t viewlightorigin;
2988 // this transforms from view space (camera) to light space (cubemap)
2989 matrix4x4_t viewtolight;
2990 matrix4x4_t lighttoview;
2991 float viewtolight16f[16];
2992 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2994 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2995 if (rtlight->currentcubemap != r_texture_whitecube)
2996 permutation |= SHADERPERMUTATION_CUBEFILTER;
2997 if (diffusescale > 0)
2998 permutation |= SHADERPERMUTATION_DIFFUSE;
2999 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3000 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3001 if (r_shadow_usingshadowmap2d)
3003 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3004 if (r_shadow_shadowmapvsdct)
3005 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3007 if (r_shadow_shadowmapsampler)
3008 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3009 if (r_shadow_shadowmappcf > 1)
3010 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3011 else if (r_shadow_shadowmappcf)
3012 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3014 if (vid.allowalphatocoverage)
3015 GL_AlphaToCoverage(false);
3016 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3017 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3018 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3019 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3020 switch(vid.renderpath)
3022 case RENDERPATH_D3D9:
3024 R_SetupShader_SetPermutationHLSL(mode, permutation);
3025 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3026 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3027 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3028 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3029 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3030 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3031 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3032 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3033 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3034 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3036 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3037 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3038 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3039 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3040 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3041 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3044 case RENDERPATH_D3D10:
3045 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3047 case RENDERPATH_D3D11:
3048 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3050 case RENDERPATH_GL20:
3051 case RENDERPATH_GLES2:
3052 R_SetupShader_SetPermutationGLSL(mode, permutation);
3053 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3054 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3055 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);
3056 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);
3057 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);
3058 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]);
3059 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]);
3060 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));
3061 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]);
3062 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3064 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3065 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3066 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3067 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3068 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3069 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3071 case RENDERPATH_GL11:
3072 case RENDERPATH_GL13:
3073 case RENDERPATH_GLES1:
3075 case RENDERPATH_SOFT:
3076 R_SetupShader_SetPermutationGLSL(mode, permutation);
3077 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3078 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3079 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3080 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3081 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3082 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3083 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]);
3084 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));
3085 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3086 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3088 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3089 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3090 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3091 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3092 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3093 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3098 #define SKINFRAME_HASH 1024
3102 int loadsequence; // incremented each level change
3103 memexpandablearray_t array;
3104 skinframe_t *hash[SKINFRAME_HASH];
3107 r_skinframe_t r_skinframe;
3109 void R_SkinFrame_PrepareForPurge(void)
3111 r_skinframe.loadsequence++;
3112 // wrap it without hitting zero
3113 if (r_skinframe.loadsequence >= 200)
3114 r_skinframe.loadsequence = 1;
3117 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3121 // mark the skinframe as used for the purging code
3122 skinframe->loadsequence = r_skinframe.loadsequence;
3125 void R_SkinFrame_Purge(void)
3129 for (i = 0;i < SKINFRAME_HASH;i++)
3131 for (s = r_skinframe.hash[i];s;s = s->next)
3133 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3135 if (s->merged == s->base)
3137 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3138 R_PurgeTexture(s->stain );s->stain = NULL;
3139 R_PurgeTexture(s->merged);s->merged = NULL;
3140 R_PurgeTexture(s->base );s->base = NULL;
3141 R_PurgeTexture(s->pants );s->pants = NULL;
3142 R_PurgeTexture(s->shirt );s->shirt = NULL;
3143 R_PurgeTexture(s->nmap );s->nmap = NULL;
3144 R_PurgeTexture(s->gloss );s->gloss = NULL;
3145 R_PurgeTexture(s->glow );s->glow = NULL;
3146 R_PurgeTexture(s->fog );s->fog = NULL;
3147 R_PurgeTexture(s->reflect);s->reflect = NULL;
3148 s->loadsequence = 0;
3154 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3156 char basename[MAX_QPATH];
3158 Image_StripImageExtension(name, basename, sizeof(basename));
3160 if( last == NULL ) {
3162 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3163 item = r_skinframe.hash[hashindex];
3168 // linearly search through the hash bucket
3169 for( ; item ; item = item->next ) {
3170 if( !strcmp( item->basename, basename ) ) {
3177 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3181 char basename[MAX_QPATH];
3183 Image_StripImageExtension(name, basename, sizeof(basename));
3185 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3186 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3187 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3191 rtexture_t *dyntexture;
3192 // check whether its a dynamic texture
3193 dyntexture = CL_GetDynTexture( basename );
3194 if (!add && !dyntexture)
3196 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3197 memset(item, 0, sizeof(*item));
3198 strlcpy(item->basename, basename, sizeof(item->basename));
3199 item->base = dyntexture; // either NULL or dyntexture handle
3200 item->textureflags = textureflags;
3201 item->comparewidth = comparewidth;
3202 item->compareheight = compareheight;
3203 item->comparecrc = comparecrc;
3204 item->next = r_skinframe.hash[hashindex];
3205 r_skinframe.hash[hashindex] = item;
3207 else if( item->base == NULL )
3209 rtexture_t *dyntexture;
3210 // check whether its a dynamic texture
3211 // 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]
3212 dyntexture = CL_GetDynTexture( basename );
3213 item->base = dyntexture; // either NULL or dyntexture handle
3216 R_SkinFrame_MarkUsed(item);
3220 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3222 unsigned long long avgcolor[5], wsum; \
3230 for(pix = 0; pix < cnt; ++pix) \
3233 for(comp = 0; comp < 3; ++comp) \
3235 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3238 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3240 for(comp = 0; comp < 3; ++comp) \
3241 avgcolor[comp] += getpixel * w; \
3244 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3245 avgcolor[4] += getpixel; \
3247 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3249 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3250 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3251 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3252 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3255 extern cvar_t gl_picmip;
3256 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3259 unsigned char *pixels;
3260 unsigned char *bumppixels;
3261 unsigned char *basepixels = NULL;
3262 int basepixels_width = 0;
3263 int basepixels_height = 0;
3264 skinframe_t *skinframe;
3265 rtexture_t *ddsbase = NULL;
3266 qboolean ddshasalpha = false;
3267 float ddsavgcolor[4];
3268 char basename[MAX_QPATH];
3269 int miplevel = R_PicmipForFlags(textureflags);
3270 int savemiplevel = miplevel;
3273 if (cls.state == ca_dedicated)
3276 // return an existing skinframe if already loaded
3277 // if loading of the first image fails, don't make a new skinframe as it
3278 // would cause all future lookups of this to be missing
3279 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3280 if (skinframe && skinframe->base)
3283 Image_StripImageExtension(name, basename, sizeof(basename));
3285 // check for DDS texture file first
3286 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3288 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3289 if (basepixels == NULL)
3293 // FIXME handle miplevel
3295 if (developer_loading.integer)
3296 Con_Printf("loading skin \"%s\"\n", name);
3298 // we've got some pixels to store, so really allocate this new texture now
3300 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3301 skinframe->stain = NULL;
3302 skinframe->merged = NULL;
3303 skinframe->base = NULL;
3304 skinframe->pants = NULL;
3305 skinframe->shirt = NULL;
3306 skinframe->nmap = NULL;
3307 skinframe->gloss = NULL;
3308 skinframe->glow = NULL;
3309 skinframe->fog = NULL;
3310 skinframe->reflect = NULL;
3311 skinframe->hasalpha = false;
3315 skinframe->base = ddsbase;
3316 skinframe->hasalpha = ddshasalpha;
3317 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3318 if (r_loadfog && skinframe->hasalpha)
3319 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3320 //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]);
3324 basepixels_width = image_width;
3325 basepixels_height = image_height;
3326 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);
3327 if (textureflags & TEXF_ALPHA)
3329 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3331 if (basepixels[j] < 255)
3333 skinframe->hasalpha = true;
3337 if (r_loadfog && skinframe->hasalpha)
3339 // has transparent pixels
3340 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3341 for (j = 0;j < image_width * image_height * 4;j += 4)
3346 pixels[j+3] = basepixels[j+3];
3348 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);
3352 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3354 //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]);
3355 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3356 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3357 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3358 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3364 mymiplevel = savemiplevel;
3365 if (r_loadnormalmap)
3366 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);
3367 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3369 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3370 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3371 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3372 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3375 // _norm is the name used by tenebrae and has been adopted as standard
3376 if (r_loadnormalmap && skinframe->nmap == NULL)
3378 mymiplevel = savemiplevel;
3379 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3381 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);
3385 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3387 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3388 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3389 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);
3391 Mem_Free(bumppixels);
3393 else if (r_shadow_bumpscale_basetexture.value > 0)
3395 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3396 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3397 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);
3401 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3402 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3406 // _luma is supported only for tenebrae compatibility
3407 // _glow is the preferred name
3408 mymiplevel = savemiplevel;
3409 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))))
3411 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);
3413 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3414 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3416 Mem_Free(pixels);pixels = NULL;
3419 mymiplevel = savemiplevel;
3420 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3422 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);
3424 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3425 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3431 mymiplevel = savemiplevel;
3432 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3434 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);
3436 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3437 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3443 mymiplevel = savemiplevel;
3444 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3446 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);
3448 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3449 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3455 mymiplevel = savemiplevel;
3456 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3458 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);
3460 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3461 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3468 Mem_Free(basepixels);
3473 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3474 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3477 unsigned char *temp1, *temp2;
3478 skinframe_t *skinframe;
3480 if (cls.state == ca_dedicated)
3483 // if already loaded just return it, otherwise make a new skinframe
3484 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3485 if (skinframe && skinframe->base)
3488 skinframe->stain = NULL;
3489 skinframe->merged = NULL;
3490 skinframe->base = NULL;
3491 skinframe->pants = NULL;
3492 skinframe->shirt = NULL;
3493 skinframe->nmap = NULL;
3494 skinframe->gloss = NULL;
3495 skinframe->glow = NULL;
3496 skinframe->fog = NULL;
3497 skinframe->reflect = NULL;
3498 skinframe->hasalpha = false;
3500 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3504 if (developer_loading.integer)
3505 Con_Printf("loading 32bit skin \"%s\"\n", name);
3507 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3509 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3510 temp2 = temp1 + width * height * 4;
3511 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3512 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);
3515 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3516 if (textureflags & TEXF_ALPHA)
3518 for (i = 3;i < width * height * 4;i += 4)
3520 if (skindata[i] < 255)
3522 skinframe->hasalpha = true;
3526 if (r_loadfog && skinframe->hasalpha)
3528 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3529 memcpy(fogpixels, skindata, width * height * 4);
3530 for (i = 0;i < width * height * 4;i += 4)
3531 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3532 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3533 Mem_Free(fogpixels);
3537 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3538 //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]);
3543 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3547 skinframe_t *skinframe;
3549 if (cls.state == ca_dedicated)
3552 // if already loaded just return it, otherwise make a new skinframe
3553 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3554 if (skinframe && skinframe->base)
3557 skinframe->stain = NULL;
3558 skinframe->merged = NULL;
3559 skinframe->base = NULL;
3560 skinframe->pants = NULL;
3561 skinframe->shirt = NULL;
3562 skinframe->nmap = NULL;
3563 skinframe->gloss = NULL;
3564 skinframe->glow = NULL;
3565 skinframe->fog = NULL;
3566 skinframe->reflect = NULL;
3567 skinframe->hasalpha = false;
3569 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3573 if (developer_loading.integer)
3574 Con_Printf("loading quake skin \"%s\"\n", name);
3576 // 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)
3577 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3578 memcpy(skinframe->qpixels, skindata, width*height);
3579 skinframe->qwidth = width;
3580 skinframe->qheight = height;
3583 for (i = 0;i < width * height;i++)
3584 featuresmask |= palette_featureflags[skindata[i]];
3586 skinframe->hasalpha = false;
3587 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3588 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3589 skinframe->qgeneratemerged = true;
3590 skinframe->qgeneratebase = skinframe->qhascolormapping;
3591 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3593 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3594 //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]);
3599 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3603 unsigned char *skindata;
3605 if (!skinframe->qpixels)
3608 if (!skinframe->qhascolormapping)
3609 colormapped = false;
3613 if (!skinframe->qgeneratebase)
3618 if (!skinframe->qgeneratemerged)
3622 width = skinframe->qwidth;
3623 height = skinframe->qheight;
3624 skindata = skinframe->qpixels;
3626 if (skinframe->qgeneratenmap)
3628 unsigned char *temp1, *temp2;
3629 skinframe->qgeneratenmap = false;
3630 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3631 temp2 = temp1 + width * height * 4;
3632 // use either a custom palette or the quake palette
3633 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3634 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3635 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);
3639 if (skinframe->qgenerateglow)
3641 skinframe->qgenerateglow = false;
3642 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
3647 skinframe->qgeneratebase = false;
3648 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);
3649 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);
3650 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);
3654 skinframe->qgeneratemerged = false;
3655 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);
3658 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3660 Mem_Free(skinframe->qpixels);
3661 skinframe->qpixels = NULL;
3665 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)
3668 skinframe_t *skinframe;
3670 if (cls.state == ca_dedicated)
3673 // if already loaded just return it, otherwise make a new skinframe
3674 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3675 if (skinframe && skinframe->base)
3678 skinframe->stain = NULL;
3679 skinframe->merged = NULL;
3680 skinframe->base = NULL;
3681 skinframe->pants = NULL;
3682 skinframe->shirt = NULL;
3683 skinframe->nmap = NULL;
3684 skinframe->gloss = NULL;
3685 skinframe->glow = NULL;
3686 skinframe->fog = NULL;
3687 skinframe->reflect = NULL;
3688 skinframe->hasalpha = false;
3690 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3694 if (developer_loading.integer)
3695 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3697 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3698 if (textureflags & TEXF_ALPHA)
3700 for (i = 0;i < width * height;i++)
3702 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3704 skinframe->hasalpha = true;
3708 if (r_loadfog && skinframe->hasalpha)
3709 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3712 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3713 //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]);
3718 skinframe_t *R_SkinFrame_LoadMissing(void)
3720 skinframe_t *skinframe;
3722 if (cls.state == ca_dedicated)
3725 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3726 skinframe->stain = NULL;
3727 skinframe->merged = NULL;
3728 skinframe->base = NULL;
3729 skinframe->pants = NULL;
3730 skinframe->shirt = NULL;
3731 skinframe->nmap = NULL;
3732 skinframe->gloss = NULL;
3733 skinframe->glow = NULL;
3734 skinframe->fog = NULL;
3735 skinframe->reflect = NULL;
3736 skinframe->hasalpha = false;
3738 skinframe->avgcolor[0] = rand() / RAND_MAX;
3739 skinframe->avgcolor[1] = rand() / RAND_MAX;
3740 skinframe->avgcolor[2] = rand() / RAND_MAX;
3741 skinframe->avgcolor[3] = 1;
3746 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3747 typedef struct suffixinfo_s
3750 qboolean flipx, flipy, flipdiagonal;
3753 static suffixinfo_t suffix[3][6] =
3756 {"px", false, false, false},
3757 {"nx", false, false, false},
3758 {"py", false, false, false},
3759 {"ny", false, false, false},
3760 {"pz", false, false, false},
3761 {"nz", false, false, false}
3764 {"posx", false, false, false},
3765 {"negx", false, false, false},
3766 {"posy", false, false, false},
3767 {"negy", false, false, false},
3768 {"posz", false, false, false},
3769 {"negz", false, false, false}
3772 {"rt", true, false, true},
3773 {"lf", false, true, true},
3774 {"ft", true, true, false},
3775 {"bk", false, false, false},
3776 {"up", true, false, true},
3777 {"dn", true, false, true}
3781 static int componentorder[4] = {0, 1, 2, 3};
3783 rtexture_t *R_LoadCubemap(const char *basename)
3785 int i, j, cubemapsize;
3786 unsigned char *cubemappixels, *image_buffer;
3787 rtexture_t *cubemaptexture;
3789 // must start 0 so the first loadimagepixels has no requested width/height
3791 cubemappixels = NULL;
3792 cubemaptexture = NULL;
3793 // keep trying different suffix groups (posx, px, rt) until one loads
3794 for (j = 0;j < 3 && !cubemappixels;j++)
3796 // load the 6 images in the suffix group
3797 for (i = 0;i < 6;i++)
3799 // generate an image name based on the base and and suffix
3800 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3802 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3804 // an image loaded, make sure width and height are equal
3805 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3807 // if this is the first image to load successfully, allocate the cubemap memory
3808 if (!cubemappixels && image_width >= 1)
3810 cubemapsize = image_width;
3811 // note this clears to black, so unavailable sides are black
3812 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3814 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3816 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);
3819 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3821 Mem_Free(image_buffer);
3825 // if a cubemap loaded, upload it
3828 if (developer_loading.integer)
3829 Con_Printf("loading cubemap \"%s\"\n", basename);
3831 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);
3832 Mem_Free(cubemappixels);
3836 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3837 if (developer_loading.integer)
3839 Con_Printf("(tried tried images ");
3840 for (j = 0;j < 3;j++)
3841 for (i = 0;i < 6;i++)
3842 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3843 Con_Print(" and was unable to find any of them).\n");
3846 return cubemaptexture;
3849 rtexture_t *R_GetCubemap(const char *basename)
3852 for (i = 0;i < r_texture_numcubemaps;i++)
3853 if (r_texture_cubemaps[i] != NULL)
3854 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3855 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3856 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3857 return r_texture_whitecube;
3858 r_texture_numcubemaps++;
3859 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3860 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3861 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3862 return r_texture_cubemaps[i]->texture;
3865 void R_FreeCubemap(const char *basename)
3869 for (i = 0;i < r_texture_numcubemaps;i++)
3871 if (r_texture_cubemaps[i] != NULL)
3873 if (r_texture_cubemaps[i]->texture)
3875 if (developer_loading.integer)
3876 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3877 R_FreeTexture(r_texture_cubemaps[i]->texture);
3878 Mem_Free(r_texture_cubemaps[i]);
3879 r_texture_cubemaps[i] = NULL;
3885 void R_FreeCubemaps(void)
3888 for (i = 0;i < r_texture_numcubemaps;i++)
3890 if (developer_loading.integer)
3891 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3892 if (r_texture_cubemaps[i] != NULL)
3894 if (r_texture_cubemaps[i]->texture)
3895 R_FreeTexture(r_texture_cubemaps[i]->texture);
3896 Mem_Free(r_texture_cubemaps[i]);
3899 r_texture_numcubemaps = 0;
3902 void R_Main_FreeViewCache(void)
3904 if (r_refdef.viewcache.entityvisible)
3905 Mem_Free(r_refdef.viewcache.entityvisible);
3906 if (r_refdef.viewcache.world_pvsbits)
3907 Mem_Free(r_refdef.viewcache.world_pvsbits);
3908 if (r_refdef.viewcache.world_leafvisible)
3909 Mem_Free(r_refdef.viewcache.world_leafvisible);
3910 if (r_refdef.viewcache.world_surfacevisible)
3911 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3912 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3915 void R_Main_ResizeViewCache(void)
3917 int numentities = r_refdef.scene.numentities;
3918 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3919 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3920 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3921 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3922 if (r_refdef.viewcache.maxentities < numentities)
3924 r_refdef.viewcache.maxentities = numentities;
3925 if (r_refdef.viewcache.entityvisible)
3926 Mem_Free(r_refdef.viewcache.entityvisible);
3927 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3929 if (r_refdef.viewcache.world_numclusters != numclusters)
3931 r_refdef.viewcache.world_numclusters = numclusters;
3932 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3933 if (r_refdef.viewcache.world_pvsbits)
3934 Mem_Free(r_refdef.viewcache.world_pvsbits);
3935 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3937 if (r_refdef.viewcache.world_numleafs != numleafs)
3939 r_refdef.viewcache.world_numleafs = numleafs;
3940 if (r_refdef.viewcache.world_leafvisible)
3941 Mem_Free(r_refdef.viewcache.world_leafvisible);
3942 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3944 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3946 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3947 if (r_refdef.viewcache.world_surfacevisible)
3948 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3949 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3953 extern rtexture_t *loadingscreentexture;
3954 void gl_main_start(void)
3956 loadingscreentexture = NULL;
3957 r_texture_blanknormalmap = NULL;
3958 r_texture_white = NULL;
3959 r_texture_grey128 = NULL;
3960 r_texture_black = NULL;
3961 r_texture_whitecube = NULL;
3962 r_texture_normalizationcube = NULL;
3963 r_texture_fogattenuation = NULL;
3964 r_texture_fogheighttexture = NULL;
3965 r_texture_gammaramps = NULL;
3966 r_texture_numcubemaps = 0;
3968 r_loaddds = r_texture_dds_load.integer != 0;
3969 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3971 switch(vid.renderpath)
3973 case RENDERPATH_GL20:
3974 case RENDERPATH_D3D9:
3975 case RENDERPATH_D3D10:
3976 case RENDERPATH_D3D11:
3977 case RENDERPATH_SOFT:
3978 case RENDERPATH_GLES2:
3979 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3980 Cvar_SetValueQuick(&gl_combine, 1);
3981 Cvar_SetValueQuick(&r_glsl, 1);
3982 r_loadnormalmap = true;
3986 case RENDERPATH_GL13:
3987 case RENDERPATH_GLES1:
3988 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3989 Cvar_SetValueQuick(&gl_combine, 1);
3990 Cvar_SetValueQuick(&r_glsl, 0);
3991 r_loadnormalmap = false;
3992 r_loadgloss = false;
3995 case RENDERPATH_GL11:
3996 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3997 Cvar_SetValueQuick(&gl_combine, 0);
3998 Cvar_SetValueQuick(&r_glsl, 0);
3999 r_loadnormalmap = false;
4000 r_loadgloss = false;
4006 R_FrameData_Reset();
4010 memset(r_queries, 0, sizeof(r_queries));
4012 r_qwskincache = NULL;
4013 r_qwskincache_size = 0;
4015 // due to caching of texture_t references, the collision cache must be reset
4016 Collision_Cache_Reset(true);
4018 // set up r_skinframe loading system for textures
4019 memset(&r_skinframe, 0, sizeof(r_skinframe));
4020 r_skinframe.loadsequence = 1;
4021 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4023 r_main_texturepool = R_AllocTexturePool();
4024 R_BuildBlankTextures();
4026 if (vid.support.arb_texture_cube_map)
4029 R_BuildNormalizationCube();
4031 r_texture_fogattenuation = NULL;
4032 r_texture_fogheighttexture = NULL;
4033 r_texture_gammaramps = NULL;
4034 //r_texture_fogintensity = NULL;
4035 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4036 memset(&r_waterstate, 0, sizeof(r_waterstate));
4037 r_glsl_permutation = NULL;
4038 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4039 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4040 glslshaderstring = NULL;
4042 r_hlsl_permutation = NULL;
4043 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4044 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4046 hlslshaderstring = NULL;
4047 memset(&r_svbsp, 0, sizeof (r_svbsp));
4049 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4050 r_texture_numcubemaps = 0;
4052 r_refdef.fogmasktable_density = 0;
4055 void gl_main_shutdown(void)
4058 R_FrameData_Reset();
4060 R_Main_FreeViewCache();
4062 switch(vid.renderpath)
4064 case RENDERPATH_GL11:
4065 case RENDERPATH_GL13:
4066 case RENDERPATH_GL20:
4067 case RENDERPATH_GLES1:
4068 case RENDERPATH_GLES2:
4069 #ifdef GL_SAMPLES_PASSED_ARB
4071 qglDeleteQueriesARB(r_maxqueries, r_queries);
4074 case RENDERPATH_D3D9:
4075 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4077 case RENDERPATH_D3D10:
4078 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4080 case RENDERPATH_D3D11:
4081 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4083 case RENDERPATH_SOFT:
4089 memset(r_queries, 0, sizeof(r_queries));
4091 r_qwskincache = NULL;
4092 r_qwskincache_size = 0;
4094 // clear out the r_skinframe state
4095 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4096 memset(&r_skinframe, 0, sizeof(r_skinframe));
4099 Mem_Free(r_svbsp.nodes);
4100 memset(&r_svbsp, 0, sizeof (r_svbsp));
4101 R_FreeTexturePool(&r_main_texturepool);
4102 loadingscreentexture = NULL;
4103 r_texture_blanknormalmap = NULL;
4104 r_texture_white = NULL;
4105 r_texture_grey128 = NULL;
4106 r_texture_black = NULL;
4107 r_texture_whitecube = NULL;
4108 r_texture_normalizationcube = NULL;
4109 r_texture_fogattenuation = NULL;
4110 r_texture_fogheighttexture = NULL;
4111 r_texture_gammaramps = NULL;
4112 r_texture_numcubemaps = 0;
4113 //r_texture_fogintensity = NULL;
4114 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4115 memset(&r_waterstate, 0, sizeof(r_waterstate));
4118 r_glsl_permutation = NULL;
4119 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4120 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4121 glslshaderstring = NULL;
4123 r_hlsl_permutation = NULL;
4124 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4125 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4127 hlslshaderstring = NULL;
4130 extern void CL_ParseEntityLump(char *entitystring);
4131 void gl_main_newmap(void)
4133 // FIXME: move this code to client
4134 char *entities, entname[MAX_QPATH];
4136 Mem_Free(r_qwskincache);
4137 r_qwskincache = NULL;
4138 r_qwskincache_size = 0;
4141 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4142 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4144 CL_ParseEntityLump(entities);
4148 if (cl.worldmodel->brush.entities)
4149 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4151 R_Main_FreeViewCache();
4153 R_FrameData_Reset();
4156 void GL_Main_Init(void)
4158 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4160 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4161 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4162 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4163 if (gamemode == GAME_NEHAHRA)
4165 Cvar_RegisterVariable (&gl_fogenable);
4166 Cvar_RegisterVariable (&gl_fogdensity);
4167 Cvar_RegisterVariable (&gl_fogred);
4168 Cvar_RegisterVariable (&gl_foggreen);
4169 Cvar_RegisterVariable (&gl_fogblue);
4170 Cvar_RegisterVariable (&gl_fogstart);
4171 Cvar_RegisterVariable (&gl_fogend);
4172 Cvar_RegisterVariable (&gl_skyclip);
4174 Cvar_RegisterVariable(&r_motionblur);
4175 Cvar_RegisterVariable(&r_damageblur);
4176 Cvar_RegisterVariable(&r_motionblur_averaging);
4177 Cvar_RegisterVariable(&r_motionblur_randomize);
4178 Cvar_RegisterVariable(&r_motionblur_minblur);
4179 Cvar_RegisterVariable(&r_motionblur_maxblur);
4180 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4181 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4182 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4183 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4184 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4185 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4186 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4187 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4188 Cvar_RegisterVariable(&r_equalize_entities_by);
4189 Cvar_RegisterVariable(&r_equalize_entities_to);
4190 Cvar_RegisterVariable(&r_depthfirst);
4191 Cvar_RegisterVariable(&r_useinfinitefarclip);
4192 Cvar_RegisterVariable(&r_farclip_base);
4193 Cvar_RegisterVariable(&r_farclip_world);
4194 Cvar_RegisterVariable(&r_nearclip);
4195 Cvar_RegisterVariable(&r_deformvertexes);
4196 Cvar_RegisterVariable(&r_transparent);
4197 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4198 Cvar_RegisterVariable(&r_showoverdraw);
4199 Cvar_RegisterVariable(&r_showbboxes);
4200 Cvar_RegisterVariable(&r_showsurfaces);
4201 Cvar_RegisterVariable(&r_showtris);
4202 Cvar_RegisterVariable(&r_shownormals);
4203 Cvar_RegisterVariable(&r_showlighting);
4204 Cvar_RegisterVariable(&r_showshadowvolumes);
4205 Cvar_RegisterVariable(&r_showcollisionbrushes);
4206 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4207 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4208 Cvar_RegisterVariable(&r_showdisabledepthtest);
4209 Cvar_RegisterVariable(&r_drawportals);
4210 Cvar_RegisterVariable(&r_drawentities);
4211 Cvar_RegisterVariable(&r_draw2d);
4212 Cvar_RegisterVariable(&r_drawworld);
4213 Cvar_RegisterVariable(&r_cullentities_trace);
4214 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4215 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4216 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4217 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4218 Cvar_RegisterVariable(&r_sortentities);
4219 Cvar_RegisterVariable(&r_drawviewmodel);
4220 Cvar_RegisterVariable(&r_drawexteriormodel);
4221 Cvar_RegisterVariable(&r_speeds);
4222 Cvar_RegisterVariable(&r_fullbrights);
4223 Cvar_RegisterVariable(&r_wateralpha);
4224 Cvar_RegisterVariable(&r_dynamic);
4225 Cvar_RegisterVariable(&r_fakelight);
4226 Cvar_RegisterVariable(&r_fakelight_intensity);
4227 Cvar_RegisterVariable(&r_fullbright);
4228 Cvar_RegisterVariable(&r_shadows);
4229 Cvar_RegisterVariable(&r_shadows_darken);
4230 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4231 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4232 Cvar_RegisterVariable(&r_shadows_throwdistance);
4233 Cvar_RegisterVariable(&r_shadows_throwdirection);
4234 Cvar_RegisterVariable(&r_shadows_focus);
4235 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4236 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4237 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4238 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4239 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4240 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4241 Cvar_RegisterVariable(&r_fog_exp2);
4242 Cvar_RegisterVariable(&r_fog_clear);
4243 Cvar_RegisterVariable(&r_drawfog);
4244 Cvar_RegisterVariable(&r_transparentdepthmasking);
4245 Cvar_RegisterVariable(&r_transparent_sortmindist);
4246 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4247 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4248 Cvar_RegisterVariable(&r_texture_dds_load);
4249 Cvar_RegisterVariable(&r_texture_dds_save);
4250 Cvar_RegisterVariable(&r_textureunits);
4251 Cvar_RegisterVariable(&gl_combine);
4252 Cvar_RegisterVariable(&r_viewfbo);
4253 Cvar_RegisterVariable(&r_viewscale);
4254 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4255 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4256 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4257 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4258 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4259 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4260 Cvar_RegisterVariable(&r_glsl);
4261 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4262 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4263 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4264 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4265 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4266 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4267 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4268 Cvar_RegisterVariable(&r_glsl_postprocess);
4269 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4270 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4271 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4272 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4273 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4274 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4275 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4276 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4278 Cvar_RegisterVariable(&r_water);
4279 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4280 Cvar_RegisterVariable(&r_water_clippingplanebias);
4281 Cvar_RegisterVariable(&r_water_refractdistort);
4282 Cvar_RegisterVariable(&r_water_reflectdistort);
4283 Cvar_RegisterVariable(&r_water_scissormode);
4284 Cvar_RegisterVariable(&r_water_lowquality);
4286 Cvar_RegisterVariable(&r_lerpsprites);
4287 Cvar_RegisterVariable(&r_lerpmodels);
4288 Cvar_RegisterVariable(&r_lerplightstyles);
4289 Cvar_RegisterVariable(&r_waterscroll);
4290 Cvar_RegisterVariable(&r_bloom);
4291 Cvar_RegisterVariable(&r_bloom_colorscale);
4292 Cvar_RegisterVariable(&r_bloom_brighten);
4293 Cvar_RegisterVariable(&r_bloom_blur);
4294 Cvar_RegisterVariable(&r_bloom_resolution);
4295 Cvar_RegisterVariable(&r_bloom_colorexponent);
4296 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4297 Cvar_RegisterVariable(&r_hdr);
4298 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4299 Cvar_RegisterVariable(&r_hdr_glowintensity);
4300 Cvar_RegisterVariable(&r_hdr_range);
4301 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4302 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4303 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4304 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4305 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4306 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4307 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4308 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4309 Cvar_RegisterVariable(&developer_texturelogging);
4310 Cvar_RegisterVariable(&gl_lightmaps);
4311 Cvar_RegisterVariable(&r_test);
4312 Cvar_RegisterVariable(&r_glsl_saturation);
4313 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4314 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4315 Cvar_RegisterVariable(&r_framedatasize);
4316 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4317 Cvar_SetValue("r_fullbrights", 0);
4318 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4321 extern void R_Textures_Init(void);
4322 extern void GL_Draw_Init(void);
4323 extern void GL_Main_Init(void);
4324 extern void R_Shadow_Init(void);
4325 extern void R_Sky_Init(void);
4326 extern void GL_Surf_Init(void);
4327 extern void R_Particles_Init(void);
4328 extern void R_Explosion_Init(void);
4329 extern void gl_backend_init(void);
4330 extern void Sbar_Init(void);
4331 extern void R_LightningBeams_Init(void);
4332 extern void Mod_RenderInit(void);
4333 extern void Font_Init(void);
4335 void Render_Init(void)
4348 R_LightningBeams_Init();
4358 extern char *ENGINE_EXTENSIONS;
4361 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4362 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4363 gl_version = (const char *)qglGetString(GL_VERSION);
4364 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4368 if (!gl_platformextensions)
4369 gl_platformextensions = "";
4371 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4372 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4373 Con_Printf("GL_VERSION: %s\n", gl_version);
4374 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4375 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4377 VID_CheckExtensions();
4379 // LordHavoc: report supported extensions
4380 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4382 // clear to black (loading plaque will be seen over this)
4383 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4387 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4391 if (r_trippy.integer)
4393 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4395 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4398 p = r_refdef.view.frustum + i;
4403 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4407 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4411 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4415 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4419 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4423 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4427 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4431 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4439 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4443 if (r_trippy.integer)
4445 for (i = 0;i < numplanes;i++)
4452 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4456 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4460 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4464 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4468 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4472 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4476 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4480 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4488 //==================================================================================
4490 // LordHavoc: this stores temporary data used within the same frame
4492 typedef struct r_framedata_mem_s
4494 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4495 size_t size; // how much usable space
4496 size_t current; // how much space in use
4497 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4498 size_t wantedsize; // how much space was allocated
4499 unsigned char *data; // start of real data (16byte aligned)
4503 static r_framedata_mem_t *r_framedata_mem;
4505 void R_FrameData_Reset(void)
4507 while (r_framedata_mem)
4509 r_framedata_mem_t *next = r_framedata_mem->purge;
4510 Mem_Free(r_framedata_mem);
4511 r_framedata_mem = next;
4515 void R_FrameData_Resize(void)
4518 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4519 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4520 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4522 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4523 newmem->wantedsize = wantedsize;
4524 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4525 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4526 newmem->current = 0;
4528 newmem->purge = r_framedata_mem;
4529 r_framedata_mem = newmem;
4533 void R_FrameData_NewFrame(void)
4535 R_FrameData_Resize();
4536 if (!r_framedata_mem)
4538 // if we ran out of space on the last frame, free the old memory now
4539 while (r_framedata_mem->purge)
4541 // repeatedly remove the second item in the list, leaving only head
4542 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4543 Mem_Free(r_framedata_mem->purge);
4544 r_framedata_mem->purge = next;
4546 // reset the current mem pointer
4547 r_framedata_mem->current = 0;
4548 r_framedata_mem->mark = 0;
4551 void *R_FrameData_Alloc(size_t size)
4555 // align to 16 byte boundary - the data pointer is already aligned, so we
4556 // only need to ensure the size of every allocation is also aligned
4557 size = (size + 15) & ~15;
4559 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4561 // emergency - we ran out of space, allocate more memory
4562 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4563 R_FrameData_Resize();
4566 data = r_framedata_mem->data + r_framedata_mem->current;
4567 r_framedata_mem->current += size;
4569 // count the usage for stats
4570 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4571 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4573 return (void *)data;
4576 void *R_FrameData_Store(size_t size, void *data)
4578 void *d = R_FrameData_Alloc(size);
4580 memcpy(d, data, size);
4584 void R_FrameData_SetMark(void)
4586 if (!r_framedata_mem)
4588 r_framedata_mem->mark = r_framedata_mem->current;
4591 void R_FrameData_ReturnToMark(void)
4593 if (!r_framedata_mem)
4595 r_framedata_mem->current = r_framedata_mem->mark;
4598 //==================================================================================
4600 // LordHavoc: animcache originally written by Echon, rewritten since then
4603 * Animation cache prevents re-generating mesh data for an animated model
4604 * multiple times in one frame for lighting, shadowing, reflections, etc.
4607 void R_AnimCache_Free(void)
4611 void R_AnimCache_ClearCache(void)
4614 entity_render_t *ent;
4616 for (i = 0;i < r_refdef.scene.numentities;i++)
4618 ent = r_refdef.scene.entities[i];
4619 ent->animcache_vertex3f = NULL;
4620 ent->animcache_normal3f = NULL;
4621 ent->animcache_svector3f = NULL;
4622 ent->animcache_tvector3f = NULL;
4623 ent->animcache_vertexmesh = NULL;
4624 ent->animcache_vertex3fbuffer = NULL;
4625 ent->animcache_vertexmeshbuffer = NULL;
4629 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4633 // check if we need the meshbuffers
4634 if (!vid.useinterleavedarrays)
4637 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4638 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4639 // TODO: upload vertex3f buffer?
4640 if (ent->animcache_vertexmesh)
4642 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4643 for (i = 0;i < numvertices;i++)
4644 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4645 if (ent->animcache_svector3f)
4646 for (i = 0;i < numvertices;i++)
4647 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4648 if (ent->animcache_tvector3f)
4649 for (i = 0;i < numvertices;i++)
4650 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4651 if (ent->animcache_normal3f)
4652 for (i = 0;i < numvertices;i++)
4653 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4654 // TODO: upload vertexmeshbuffer?
4658 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4660 dp_model_t *model = ent->model;
4662 // see if it's already cached this frame
4663 if (ent->animcache_vertex3f)
4665 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4666 if (wantnormals || wanttangents)
4668 if (ent->animcache_normal3f)
4669 wantnormals = false;
4670 if (ent->animcache_svector3f)
4671 wanttangents = false;
4672 if (wantnormals || wanttangents)
4674 numvertices = model->surfmesh.num_vertices;
4676 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4679 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4680 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4682 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4683 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4689 // see if this ent is worth caching
4690 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4692 // get some memory for this entity and generate mesh data
4693 numvertices = model->surfmesh.num_vertices;
4694 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4696 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4699 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4700 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4702 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4703 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4708 void R_AnimCache_CacheVisibleEntities(void)
4711 qboolean wantnormals = true;
4712 qboolean wanttangents = !r_showsurfaces.integer;
4714 switch(vid.renderpath)
4716 case RENDERPATH_GL20:
4717 case RENDERPATH_D3D9:
4718 case RENDERPATH_D3D10:
4719 case RENDERPATH_D3D11:
4720 case RENDERPATH_GLES2:
4722 case RENDERPATH_GL11:
4723 case RENDERPATH_GL13:
4724 case RENDERPATH_GLES1:
4725 wanttangents = false;
4727 case RENDERPATH_SOFT:
4731 if (r_shownormals.integer)
4732 wanttangents = wantnormals = true;
4734 // TODO: thread this
4735 // NOTE: R_PrepareRTLights() also caches entities
4737 for (i = 0;i < r_refdef.scene.numentities;i++)
4738 if (r_refdef.viewcache.entityvisible[i])
4739 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4742 //==================================================================================
4744 extern cvar_t r_overheadsprites_pushback;
4746 static void R_View_UpdateEntityLighting (void)
4749 entity_render_t *ent;
4750 vec3_t tempdiffusenormal, avg;
4751 vec_t f, fa, fd, fdd;
4752 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4754 for (i = 0;i < r_refdef.scene.numentities;i++)
4756 ent = r_refdef.scene.entities[i];
4758 // skip unseen models
4759 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4763 if (ent->model && ent->model->brush.num_leafs)
4765 // TODO: use modellight for r_ambient settings on world?
4766 VectorSet(ent->modellight_ambient, 0, 0, 0);
4767 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4768 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4772 // fetch the lighting from the worldmodel data
4773 VectorClear(ent->modellight_ambient);
4774 VectorClear(ent->modellight_diffuse);
4775 VectorClear(tempdiffusenormal);
4776 if (ent->flags & RENDER_LIGHT)
4779 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4781 // complete lightning for lit sprites
4782 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4783 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4785 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4786 org[2] = org[2] + r_overheadsprites_pushback.value;
4787 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4790 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4792 if(ent->flags & RENDER_EQUALIZE)
4794 // first fix up ambient lighting...
4795 if(r_equalize_entities_minambient.value > 0)
4797 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4800 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4801 if(fa < r_equalize_entities_minambient.value * fd)
4804 // fa'/fd' = minambient
4805 // fa'+0.25*fd' = fa+0.25*fd
4807 // fa' = fd' * minambient
4808 // fd'*(0.25+minambient) = fa+0.25*fd
4810 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4811 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4813 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4814 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
4815 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4816 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4821 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4823 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4824 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4828 // adjust brightness and saturation to target
4829 avg[0] = avg[1] = avg[2] = fa / f;
4830 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4831 avg[0] = avg[1] = avg[2] = fd / f;
4832 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4838 VectorSet(ent->modellight_ambient, 1, 1, 1);
4840 // move the light direction into modelspace coordinates for lighting code
4841 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4842 if(VectorLength2(ent->modellight_lightdir) == 0)
4843 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4844 VectorNormalize(ent->modellight_lightdir);
4848 #define MAX_LINEOFSIGHTTRACES 64
4850 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4853 vec3_t boxmins, boxmaxs;
4856 dp_model_t *model = r_refdef.scene.worldmodel;
4858 if (!model || !model->brush.TraceLineOfSight)
4861 // expand the box a little
4862 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4863 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4864 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4865 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4866 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4867 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4869 // return true if eye is inside enlarged box
4870 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4874 VectorCopy(eye, start);
4875 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4876 if (model->brush.TraceLineOfSight(model, start, end))
4879 // try various random positions
4880 for (i = 0;i < numsamples;i++)
4882 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4883 if (model->brush.TraceLineOfSight(model, start, end))
4891 static void R_View_UpdateEntityVisible (void)
4896 entity_render_t *ent;
4898 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4899 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4900 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4901 : RENDER_EXTERIORMODEL;
4902 if (!r_drawviewmodel.integer)
4903 renderimask |= RENDER_VIEWMODEL;
4904 if (!r_drawexteriormodel.integer)
4905 renderimask |= RENDER_EXTERIORMODEL;
4906 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4908 // worldmodel can check visibility
4909 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4910 for (i = 0;i < r_refdef.scene.numentities;i++)
4912 ent = r_refdef.scene.entities[i];
4913 if (!(ent->flags & renderimask))
4914 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)))
4915 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))
4916 r_refdef.viewcache.entityvisible[i] = true;
4921 // no worldmodel or it can't check visibility
4922 for (i = 0;i < r_refdef.scene.numentities;i++)
4924 ent = r_refdef.scene.entities[i];
4925 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));
4928 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4929 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4931 for (i = 0;i < r_refdef.scene.numentities;i++)
4933 if (!r_refdef.viewcache.entityvisible[i])
4935 ent = r_refdef.scene.entities[i];
4936 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4938 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4940 continue; // temp entities do pvs only
4941 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4942 ent->last_trace_visibility = realtime;
4943 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4944 r_refdef.viewcache.entityvisible[i] = 0;
4950 /// only used if skyrendermasked, and normally returns false
4951 int R_DrawBrushModelsSky (void)
4954 entity_render_t *ent;
4957 for (i = 0;i < r_refdef.scene.numentities;i++)
4959 if (!r_refdef.viewcache.entityvisible[i])
4961 ent = r_refdef.scene.entities[i];
4962 if (!ent->model || !ent->model->DrawSky)
4964 ent->model->DrawSky(ent);
4970 static void R_DrawNoModel(entity_render_t *ent);
4971 static void R_DrawModels(void)
4974 entity_render_t *ent;
4976 for (i = 0;i < r_refdef.scene.numentities;i++)
4978 if (!r_refdef.viewcache.entityvisible[i])
4980 ent = r_refdef.scene.entities[i];
4981 r_refdef.stats.entities++;
4983 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4986 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4987 Con_Printf("R_DrawModels\n");
4988 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]);
4989 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);
4990 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);
4993 if (ent->model && ent->model->Draw != NULL)
4994 ent->model->Draw(ent);
5000 static void R_DrawModelsDepth(void)
5003 entity_render_t *ent;
5005 for (i = 0;i < r_refdef.scene.numentities;i++)
5007 if (!r_refdef.viewcache.entityvisible[i])
5009 ent = r_refdef.scene.entities[i];
5010 if (ent->model && ent->model->DrawDepth != NULL)
5011 ent->model->DrawDepth(ent);
5015 static void R_DrawModelsDebug(void)
5018 entity_render_t *ent;
5020 for (i = 0;i < r_refdef.scene.numentities;i++)
5022 if (!r_refdef.viewcache.entityvisible[i])
5024 ent = r_refdef.scene.entities[i];
5025 if (ent->model && ent->model->DrawDebug != NULL)
5026 ent->model->DrawDebug(ent);
5030 static void R_DrawModelsAddWaterPlanes(void)
5033 entity_render_t *ent;
5035 for (i = 0;i < r_refdef.scene.numentities;i++)
5037 if (!r_refdef.viewcache.entityvisible[i])
5039 ent = r_refdef.scene.entities[i];
5040 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5041 ent->model->DrawAddWaterPlanes(ent);
5045 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5047 if (r_hdr_irisadaptation.integer)
5051 vec3_t diffusenormal;
5055 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5056 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5057 brightness = max(0.0000001f, brightness);
5058 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5059 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5060 current = r_hdr_irisadaptation_value.value;
5062 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5063 else if (current > goal)
5064 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5065 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5066 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5068 else if (r_hdr_irisadaptation_value.value != 1.0f)
5069 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5072 static void R_View_SetFrustum(const int *scissor)
5075 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5076 vec3_t forward, left, up, origin, v;
5080 // flipped x coordinates (because x points left here)
5081 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5082 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5084 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5085 switch(vid.renderpath)
5087 case RENDERPATH_D3D9:
5088 case RENDERPATH_D3D10:
5089 case RENDERPATH_D3D11:
5090 // non-flipped y coordinates
5091 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5092 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5094 case RENDERPATH_SOFT:
5095 case RENDERPATH_GL11:
5096 case RENDERPATH_GL13:
5097 case RENDERPATH_GL20:
5098 case RENDERPATH_GLES1:
5099 case RENDERPATH_GLES2:
5100 // non-flipped y coordinates
5101 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5102 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5107 // we can't trust r_refdef.view.forward and friends in reflected scenes
5108 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5111 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5112 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5113 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5114 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5115 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5116 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5117 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5118 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5119 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5120 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5121 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5122 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5126 zNear = r_refdef.nearclip;
5127 nudge = 1.0 - 1.0 / (1<<23);
5128 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5129 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5130 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5131 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5132 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5133 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5134 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5135 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5141 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5142 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5143 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5144 r_refdef.view.frustum[0].dist = m[15] - m[12];
5146 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5147 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5148 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5149 r_refdef.view.frustum[1].dist = m[15] + m[12];
5151 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5152 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5153 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5154 r_refdef.view.frustum[2].dist = m[15] - m[13];
5156 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5157 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5158 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5159 r_refdef.view.frustum[3].dist = m[15] + m[13];
5161 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5162 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5163 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5164 r_refdef.view.frustum[4].dist = m[15] - m[14];
5166 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5167 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5168 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5169 r_refdef.view.frustum[5].dist = m[15] + m[14];
5172 if (r_refdef.view.useperspective)
5174 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5175 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]);
5176 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]);
5177 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]);
5178 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]);
5180 // then the normals from the corners relative to origin
5181 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5182 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5183 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5184 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5186 // in a NORMAL view, forward cross left == up
5187 // in a REFLECTED view, forward cross left == down
5188 // so our cross products above need to be adjusted for a left handed coordinate system
5189 CrossProduct(forward, left, v);
5190 if(DotProduct(v, up) < 0)
5192 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5193 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5194 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5195 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5198 // Leaving those out was a mistake, those were in the old code, and they
5199 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5200 // I couldn't reproduce it after adding those normalizations. --blub
5201 VectorNormalize(r_refdef.view.frustum[0].normal);
5202 VectorNormalize(r_refdef.view.frustum[1].normal);
5203 VectorNormalize(r_refdef.view.frustum[2].normal);
5204 VectorNormalize(r_refdef.view.frustum[3].normal);
5206 // make the corners absolute
5207 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5208 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5209 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5210 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5213 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5215 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5216 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5217 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5218 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5219 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5223 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5224 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5225 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5226 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5227 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) + r_refdef.view.ortho_x;
5229 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5230 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5231 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5232 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5234 r_refdef.view.numfrustumplanes = 5;
5236 if (r_refdef.view.useclipplane)
5238 r_refdef.view.numfrustumplanes = 6;
5239 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5242 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5243 PlaneClassify(r_refdef.view.frustum + i);
5245 // LordHavoc: note to all quake engine coders, Quake had a special case
5246 // for 90 degrees which assumed a square view (wrong), so I removed it,
5247 // Quake2 has it disabled as well.
5249 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5250 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5251 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5252 //PlaneClassify(&frustum[0]);
5254 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5255 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5256 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5257 //PlaneClassify(&frustum[1]);
5259 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5260 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5261 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5262 //PlaneClassify(&frustum[2]);
5264 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5265 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5266 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5267 //PlaneClassify(&frustum[3]);
5270 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5271 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5272 //PlaneClassify(&frustum[4]);
5275 void R_View_UpdateWithScissor(const int *myscissor)
5277 R_Main_ResizeViewCache();
5278 R_View_SetFrustum(myscissor);
5279 R_View_WorldVisibility(r_refdef.view.useclipplane);
5280 R_View_UpdateEntityVisible();
5281 R_View_UpdateEntityLighting();
5284 void R_View_Update(void)
5286 R_Main_ResizeViewCache();
5287 R_View_SetFrustum(NULL);
5288 R_View_WorldVisibility(r_refdef.view.useclipplane);
5289 R_View_UpdateEntityVisible();
5290 R_View_UpdateEntityLighting();
5293 float viewscalefpsadjusted = 1.0f;
5295 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5297 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5298 scale = bound(0.03125f, scale, 1.0f);
5299 *outwidth = (int)ceil(width * scale);
5300 *outheight = (int)ceil(height * scale);
5303 void R_Mesh_SetMainRenderTargets(void)
5305 if (r_bloomstate.fbo_framebuffer)
5306 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5308 R_Mesh_ResetRenderTargets();
5311 void R_SetupView(qboolean allowwaterclippingplane)
5313 const float *customclipplane = NULL;
5315 int scaledwidth, scaledheight;
5316 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5318 // LordHavoc: couldn't figure out how to make this approach the
5319 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5320 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5321 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5322 dist = r_refdef.view.clipplane.dist;
5323 plane[0] = r_refdef.view.clipplane.normal[0];
5324 plane[1] = r_refdef.view.clipplane.normal[1];
5325 plane[2] = r_refdef.view.clipplane.normal[2];
5327 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5330 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5331 if (!r_refdef.view.useperspective)
5332 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);
5333 else if (vid.stencil && r_useinfinitefarclip.integer)
5334 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);
5336 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);
5337 R_Mesh_SetMainRenderTargets();
5338 R_SetViewport(&r_refdef.view.viewport);
5339 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5341 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5342 float screenplane[4];
5343 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5344 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5345 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5346 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5347 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5351 void R_EntityMatrix(const matrix4x4_t *matrix)
5353 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5355 gl_modelmatrixchanged = false;
5356 gl_modelmatrix = *matrix;
5357 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5358 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5359 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5360 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5362 switch(vid.renderpath)
5364 case RENDERPATH_D3D9:
5366 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5367 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5370 case RENDERPATH_D3D10:
5371 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5373 case RENDERPATH_D3D11:
5374 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5376 case RENDERPATH_GL11:
5377 case RENDERPATH_GL13:
5378 case RENDERPATH_GLES1:
5379 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5381 case RENDERPATH_SOFT:
5382 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5383 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5385 case RENDERPATH_GL20:
5386 case RENDERPATH_GLES2:
5387 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5388 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5394 void R_ResetViewRendering2D(void)
5396 r_viewport_t viewport;
5399 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5400 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);
5401 R_Mesh_ResetRenderTargets();
5402 R_SetViewport(&viewport);
5403 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5404 GL_Color(1, 1, 1, 1);
5405 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5406 GL_BlendFunc(GL_ONE, GL_ZERO);
5407 GL_ScissorTest(false);
5408 GL_DepthMask(false);
5409 GL_DepthRange(0, 1);
5410 GL_DepthTest(false);
5411 GL_DepthFunc(GL_LEQUAL);
5412 R_EntityMatrix(&identitymatrix);
5413 R_Mesh_ResetTextureState();
5414 GL_PolygonOffset(0, 0);
5415 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5416 switch(vid.renderpath)
5418 case RENDERPATH_GL11:
5419 case RENDERPATH_GL13:
5420 case RENDERPATH_GL20:
5421 case RENDERPATH_GLES1:
5422 case RENDERPATH_GLES2:
5423 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5425 case RENDERPATH_D3D9:
5426 case RENDERPATH_D3D10:
5427 case RENDERPATH_D3D11:
5428 case RENDERPATH_SOFT:
5431 GL_CullFace(GL_NONE);
5434 void R_ResetViewRendering3D(void)
5439 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5440 GL_Color(1, 1, 1, 1);
5441 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5442 GL_BlendFunc(GL_ONE, GL_ZERO);
5443 GL_ScissorTest(true);
5445 GL_DepthRange(0, 1);
5447 GL_DepthFunc(GL_LEQUAL);
5448 R_EntityMatrix(&identitymatrix);
5449 R_Mesh_ResetTextureState();
5450 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5451 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5452 switch(vid.renderpath)
5454 case RENDERPATH_GL11:
5455 case RENDERPATH_GL13:
5456 case RENDERPATH_GL20:
5457 case RENDERPATH_GLES1:
5458 case RENDERPATH_GLES2:
5459 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5461 case RENDERPATH_D3D9:
5462 case RENDERPATH_D3D10:
5463 case RENDERPATH_D3D11:
5464 case RENDERPATH_SOFT:
5467 GL_CullFace(r_refdef.view.cullface_back);
5472 R_RenderView_UpdateViewVectors
5475 static void R_RenderView_UpdateViewVectors(void)
5477 // break apart the view matrix into vectors for various purposes
5478 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5479 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5480 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5481 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5482 // make an inverted copy of the view matrix for tracking sprites
5483 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5486 void R_RenderScene(void);
5487 void R_RenderWaterPlanes(void);
5489 static void R_Water_StartFrame(void)
5492 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5493 r_waterstate_waterplane_t *p;
5495 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5498 switch(vid.renderpath)
5500 case RENDERPATH_GL20:
5501 case RENDERPATH_D3D9:
5502 case RENDERPATH_D3D10:
5503 case RENDERPATH_D3D11:
5504 case RENDERPATH_SOFT:
5505 case RENDERPATH_GLES2:
5507 case RENDERPATH_GL11:
5508 case RENDERPATH_GL13:
5509 case RENDERPATH_GLES1:
5513 // set waterwidth and waterheight to the water resolution that will be
5514 // used (often less than the screen resolution for faster rendering)
5515 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5517 // calculate desired texture sizes
5518 // can't use water if the card does not support the texture size
5519 if (!r_water.integer || r_showsurfaces.integer)
5520 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5521 else if (vid.support.arb_texture_non_power_of_two)
5523 texturewidth = waterwidth;
5524 textureheight = waterheight;
5525 camerawidth = waterwidth;
5526 cameraheight = waterheight;
5530 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5531 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5532 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5533 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5536 // allocate textures as needed
5537 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5539 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5540 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5542 if (p->texture_refraction)
5543 R_FreeTexture(p->texture_refraction);
5544 p->texture_refraction = NULL;
5545 if (p->texture_reflection)
5546 R_FreeTexture(p->texture_reflection);
5547 p->texture_reflection = NULL;
5548 if (p->texture_camera)
5549 R_FreeTexture(p->texture_camera);
5550 p->texture_camera = NULL;
5552 memset(&r_waterstate, 0, sizeof(r_waterstate));
5553 r_waterstate.texturewidth = texturewidth;
5554 r_waterstate.textureheight = textureheight;
5555 r_waterstate.camerawidth = camerawidth;
5556 r_waterstate.cameraheight = cameraheight;
5559 if (r_waterstate.texturewidth)
5561 int scaledwidth, scaledheight;
5563 r_waterstate.enabled = true;
5565 // when doing a reduced render (HDR) we want to use a smaller area
5566 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5567 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5568 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5570 // set up variables that will be used in shader setup
5571 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5572 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5573 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5574 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5577 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5578 r_waterstate.numwaterplanes = 0;
5581 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5583 int triangleindex, planeindex;
5589 r_waterstate_waterplane_t *p;
5590 texture_t *t = R_GetCurrentTexture(surface->texture);
5592 // just use the first triangle with a valid normal for any decisions
5593 VectorClear(normal);
5594 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5596 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5597 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5598 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5599 TriangleNormal(vert[0], vert[1], vert[2], normal);
5600 if (VectorLength2(normal) >= 0.001)
5604 VectorCopy(normal, plane.normal);
5605 VectorNormalize(plane.normal);
5606 plane.dist = DotProduct(vert[0], plane.normal);
5607 PlaneClassify(&plane);
5608 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5610 // skip backfaces (except if nocullface is set)
5611 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5613 VectorNegate(plane.normal, plane.normal);
5615 PlaneClassify(&plane);
5619 // find a matching plane if there is one
5620 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5621 if(p->camera_entity == t->camera_entity)
5622 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5624 if (planeindex >= r_waterstate.maxwaterplanes)
5625 return; // nothing we can do, out of planes
5627 // if this triangle does not fit any known plane rendered this frame, add one
5628 if (planeindex >= r_waterstate.numwaterplanes)
5630 // store the new plane
5631 r_waterstate.numwaterplanes++;
5633 // clear materialflags and pvs
5634 p->materialflags = 0;
5635 p->pvsvalid = false;
5636 p->camera_entity = t->camera_entity;
5637 VectorCopy(surface->mins, p->mins);
5638 VectorCopy(surface->maxs, p->maxs);
5643 p->mins[0] = min(p->mins[0], surface->mins[0]);
5644 p->mins[1] = min(p->mins[1], surface->mins[1]);
5645 p->mins[2] = min(p->mins[2], surface->mins[2]);
5646 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5647 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5648 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5650 // merge this surface's materialflags into the waterplane
5651 p->materialflags |= t->currentmaterialflags;
5652 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5654 // merge this surface's PVS into the waterplane
5655 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5656 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5657 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5659 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5665 extern cvar_t r_drawparticles;
5666 extern cvar_t r_drawdecals;
5668 static void R_Water_ProcessPlanes(void)
5671 r_refdef_view_t originalview;
5672 r_refdef_view_t myview;
5673 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;
5674 r_waterstate_waterplane_t *p;
5677 originalview = r_refdef.view;
5679 // lowquality hack, temporarily shut down some cvars and restore afterwards
5680 qualityreduction = r_water_lowquality.integer;
5681 if (qualityreduction > 0)
5683 if (qualityreduction >= 1)
5685 old_r_shadows = r_shadows.integer;
5686 old_r_worldrtlight = r_shadow_realtime_world.integer;
5687 old_r_dlight = r_shadow_realtime_dlight.integer;
5688 Cvar_SetValueQuick(&r_shadows, 0);
5689 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5690 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5692 if (qualityreduction >= 2)
5694 old_r_dynamic = r_dynamic.integer;
5695 old_r_particles = r_drawparticles.integer;
5696 old_r_decals = r_drawdecals.integer;
5697 Cvar_SetValueQuick(&r_dynamic, 0);
5698 Cvar_SetValueQuick(&r_drawparticles, 0);
5699 Cvar_SetValueQuick(&r_drawdecals, 0);
5703 // make sure enough textures are allocated
5704 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5706 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5708 if (!p->texture_refraction)
5709 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);
5710 if (!p->texture_refraction)
5713 else if (p->materialflags & MATERIALFLAG_CAMERA)
5715 if (!p->texture_camera)
5716 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);
5717 if (!p->texture_camera)
5721 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5723 if (!p->texture_reflection)
5724 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);
5725 if (!p->texture_reflection)
5731 r_refdef.view = originalview;
5732 r_refdef.view.showdebug = false;
5733 r_refdef.view.width = r_waterstate.waterwidth;
5734 r_refdef.view.height = r_waterstate.waterheight;
5735 r_refdef.view.useclipplane = true;
5736 myview = r_refdef.view;
5737 r_waterstate.renderingscene = true;
5738 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5740 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5742 r_refdef.view = myview;
5743 if(r_water_scissormode.integer)
5746 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5747 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5750 // render reflected scene and copy into texture
5751 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5752 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5753 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5754 r_refdef.view.clipplane = p->plane;
5755 // reverse the cullface settings for this render
5756 r_refdef.view.cullface_front = GL_FRONT;
5757 r_refdef.view.cullface_back = GL_BACK;
5758 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5760 r_refdef.view.usecustompvs = true;
5762 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5764 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5767 R_ResetViewRendering3D();
5768 R_ClearScreen(r_refdef.fogenabled);
5769 if(r_water_scissormode.integer & 2)
5770 R_View_UpdateWithScissor(myscissor);
5773 if(r_water_scissormode.integer & 1)
5774 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5777 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);
5780 // render the normal view scene and copy into texture
5781 // (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)
5782 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5784 r_refdef.view = myview;
5785 if(r_water_scissormode.integer)
5788 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5789 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5792 r_waterstate.renderingrefraction = true;
5794 r_refdef.view.clipplane = p->plane;
5795 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5796 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5798 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5800 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5801 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5802 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5803 R_RenderView_UpdateViewVectors();
5804 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5806 r_refdef.view.usecustompvs = true;
5807 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);
5811 PlaneClassify(&r_refdef.view.clipplane);
5813 R_ResetViewRendering3D();
5814 R_ClearScreen(r_refdef.fogenabled);
5815 if(r_water_scissormode.integer & 2)
5816 R_View_UpdateWithScissor(myscissor);
5819 if(r_water_scissormode.integer & 1)
5820 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5823 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);
5824 r_waterstate.renderingrefraction = false;
5826 else if (p->materialflags & MATERIALFLAG_CAMERA)
5828 r_refdef.view = myview;
5830 r_refdef.view.clipplane = p->plane;
5831 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5832 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5834 r_refdef.view.width = r_waterstate.camerawidth;
5835 r_refdef.view.height = r_waterstate.cameraheight;
5836 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5837 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5839 if(p->camera_entity)
5841 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5842 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5845 // note: all of the view is used for displaying... so
5846 // there is no use in scissoring
5848 // reverse the cullface settings for this render
5849 r_refdef.view.cullface_front = GL_FRONT;
5850 r_refdef.view.cullface_back = GL_BACK;
5851 // also reverse the view matrix
5852 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
5853 R_RenderView_UpdateViewVectors();
5854 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5856 r_refdef.view.usecustompvs = true;
5857 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);
5860 // camera needs no clipplane
5861 r_refdef.view.useclipplane = false;
5863 PlaneClassify(&r_refdef.view.clipplane);
5865 R_ResetViewRendering3D();
5866 R_ClearScreen(r_refdef.fogenabled);
5870 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);
5871 r_waterstate.renderingrefraction = false;
5875 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5876 r_waterstate.renderingscene = false;
5877 r_refdef.view = originalview;
5878 R_ResetViewRendering3D();
5879 R_ClearScreen(r_refdef.fogenabled);
5883 r_refdef.view = originalview;
5884 r_waterstate.renderingscene = false;
5885 Cvar_SetValueQuick(&r_water, 0);
5886 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5888 // lowquality hack, restore cvars
5889 if (qualityreduction > 0)
5891 if (qualityreduction >= 1)
5893 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5894 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5895 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5897 if (qualityreduction >= 2)
5899 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5900 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5901 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5906 void R_Bloom_StartFrame(void)
5908 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5909 int viewwidth, viewheight;
5912 if (r_viewscale_fpsscaling.integer)
5914 double actualframetime;
5915 double targetframetime;
5917 actualframetime = r_refdef.lastdrawscreentime;
5918 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5919 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5920 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5921 if (r_viewscale_fpsscaling_stepsize.value > 0)
5922 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5923 viewscalefpsadjusted += adjust;
5924 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5927 viewscalefpsadjusted = 1.0f;
5929 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5931 switch(vid.renderpath)
5933 case RENDERPATH_GL20:
5934 case RENDERPATH_D3D9:
5935 case RENDERPATH_D3D10:
5936 case RENDERPATH_D3D11:
5937 case RENDERPATH_SOFT:
5938 case RENDERPATH_GLES2:
5940 case RENDERPATH_GL11:
5941 case RENDERPATH_GL13:
5942 case RENDERPATH_GLES1:
5946 // set bloomwidth and bloomheight to the bloom resolution that will be
5947 // used (often less than the screen resolution for faster rendering)
5948 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5949 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5950 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5951 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5952 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5954 // calculate desired texture sizes
5955 if (vid.support.arb_texture_non_power_of_two)
5957 screentexturewidth = vid.width;
5958 screentextureheight = vid.height;
5959 bloomtexturewidth = r_bloomstate.bloomwidth;
5960 bloomtextureheight = r_bloomstate.bloomheight;
5964 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5965 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5966 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5967 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5970 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))
5972 Cvar_SetValueQuick(&r_hdr, 0);
5973 Cvar_SetValueQuick(&r_bloom, 0);
5974 Cvar_SetValueQuick(&r_motionblur, 0);
5975 Cvar_SetValueQuick(&r_damageblur, 0);
5978 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)
5979 screentexturewidth = screentextureheight = 0;
5980 if (!r_hdr.integer && !r_bloom.integer)
5981 bloomtexturewidth = bloomtextureheight = 0;
5983 textype = TEXTYPE_COLORBUFFER;
5984 switch (vid.renderpath)
5986 case RENDERPATH_GL20:
5987 case RENDERPATH_GLES2:
5988 if (vid.support.ext_framebuffer_object)
5990 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5991 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5994 case RENDERPATH_GL11:
5995 case RENDERPATH_GL13:
5996 case RENDERPATH_GLES1:
5997 case RENDERPATH_D3D9:
5998 case RENDERPATH_D3D10:
5999 case RENDERPATH_D3D11:
6000 case RENDERPATH_SOFT:
6004 // allocate textures as needed
6005 if (r_bloomstate.screentexturewidth != screentexturewidth
6006 || r_bloomstate.screentextureheight != screentextureheight
6007 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6008 || r_bloomstate.bloomtextureheight != bloomtextureheight
6009 || r_bloomstate.texturetype != textype
6010 || r_bloomstate.viewfbo != r_viewfbo.integer)
6012 if (r_bloomstate.texture_bloom)
6013 R_FreeTexture(r_bloomstate.texture_bloom);
6014 r_bloomstate.texture_bloom = NULL;
6015 if (r_bloomstate.texture_screen)
6016 R_FreeTexture(r_bloomstate.texture_screen);
6017 r_bloomstate.texture_screen = NULL;
6018 if (r_bloomstate.fbo_framebuffer)
6019 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6020 r_bloomstate.fbo_framebuffer = 0;
6021 if (r_bloomstate.texture_framebuffercolor)
6022 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6023 r_bloomstate.texture_framebuffercolor = NULL;
6024 if (r_bloomstate.texture_framebufferdepth)
6025 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6026 r_bloomstate.texture_framebufferdepth = NULL;
6027 r_bloomstate.screentexturewidth = screentexturewidth;
6028 r_bloomstate.screentextureheight = screentextureheight;
6029 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6030 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);
6031 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6033 // FIXME: choose depth bits based on a cvar
6034 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6035 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);
6036 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6037 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6039 // render depth into one texture and normalmap into the other
6043 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6044 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6045 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6046 if (status != GL_FRAMEBUFFER_COMPLETE)
6047 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6051 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6052 r_bloomstate.bloomtextureheight = bloomtextureheight;
6053 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6054 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);
6055 r_bloomstate.viewfbo = r_viewfbo.integer;
6056 r_bloomstate.texturetype = textype;
6059 // when doing a reduced render (HDR) we want to use a smaller area
6060 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6061 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6062 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6063 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6064 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6066 // set up a texcoord array for the full resolution screen image
6067 // (we have to keep this around to copy back during final render)
6068 r_bloomstate.screentexcoord2f[0] = 0;
6069 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6070 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6071 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6072 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6073 r_bloomstate.screentexcoord2f[5] = 0;
6074 r_bloomstate.screentexcoord2f[6] = 0;
6075 r_bloomstate.screentexcoord2f[7] = 0;
6077 // set up a texcoord array for the reduced resolution bloom image
6078 // (which will be additive blended over the screen image)
6079 r_bloomstate.bloomtexcoord2f[0] = 0;
6080 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6081 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6082 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6083 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6084 r_bloomstate.bloomtexcoord2f[5] = 0;
6085 r_bloomstate.bloomtexcoord2f[6] = 0;
6086 r_bloomstate.bloomtexcoord2f[7] = 0;
6088 switch(vid.renderpath)
6090 case RENDERPATH_GL11:
6091 case RENDERPATH_GL13:
6092 case RENDERPATH_GL20:
6093 case RENDERPATH_SOFT:
6094 case RENDERPATH_GLES1:
6095 case RENDERPATH_GLES2:
6097 case RENDERPATH_D3D9:
6098 case RENDERPATH_D3D10:
6099 case RENDERPATH_D3D11:
6102 for (i = 0;i < 4;i++)
6104 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6105 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6106 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6107 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6113 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6115 r_bloomstate.enabled = true;
6116 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6119 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);
6121 if (r_bloomstate.fbo_framebuffer)
6122 r_refdef.view.clear = true;
6125 void R_Bloom_CopyBloomTexture(float colorscale)
6127 r_refdef.stats.bloom++;
6129 // scale down screen texture to the bloom texture size
6131 R_Mesh_SetMainRenderTargets();
6132 R_SetViewport(&r_bloomstate.viewport);
6133 GL_BlendFunc(GL_ONE, GL_ZERO);
6134 GL_Color(colorscale, colorscale, colorscale, 1);
6135 // 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...
6136 switch(vid.renderpath)
6138 case RENDERPATH_GL11:
6139 case RENDERPATH_GL13:
6140 case RENDERPATH_GL20:
6141 case RENDERPATH_GLES1:
6142 case RENDERPATH_GLES2:
6143 case RENDERPATH_SOFT:
6144 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6146 case RENDERPATH_D3D9:
6147 case RENDERPATH_D3D10:
6148 case RENDERPATH_D3D11:
6149 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6152 // TODO: do boxfilter scale-down in shader?
6153 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6154 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6155 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6157 // we now have a bloom image in the framebuffer
6158 // copy it into the bloom image texture for later processing
6159 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);
6160 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6163 void R_Bloom_CopyHDRTexture(void)
6165 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);
6166 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6169 void R_Bloom_MakeTexture(void)
6172 float xoffset, yoffset, r, brighten;
6174 r_refdef.stats.bloom++;
6176 R_ResetViewRendering2D();
6178 // we have a bloom image in the framebuffer
6180 R_SetViewport(&r_bloomstate.viewport);
6182 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6185 r = bound(0, r_bloom_colorexponent.value / x, 1);
6186 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6188 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6189 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6190 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6191 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6193 // copy the vertically blurred bloom view to a texture
6194 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);
6195 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6198 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6199 brighten = r_bloom_brighten.value;
6200 if (r_bloomstate.hdr)
6201 brighten *= r_hdr_range.value;
6202 brighten = sqrt(brighten);
6204 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6205 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6207 for (dir = 0;dir < 2;dir++)
6209 // blend on at multiple vertical offsets to achieve a vertical blur
6210 // TODO: do offset blends using GLSL
6211 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6212 GL_BlendFunc(GL_ONE, GL_ZERO);
6213 for (x = -range;x <= range;x++)
6215 if (!dir){xoffset = 0;yoffset = x;}
6216 else {xoffset = x;yoffset = 0;}
6217 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6218 yoffset /= (float)r_bloomstate.bloomtextureheight;
6219 // compute a texcoord array with the specified x and y offset
6220 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6221 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6222 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6223 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6224 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6225 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6226 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6227 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6228 // this r value looks like a 'dot' particle, fading sharply to
6229 // black at the edges
6230 // (probably not realistic but looks good enough)
6231 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6232 //r = brighten/(range*2+1);
6233 r = brighten / (range * 2 + 1);
6235 r *= (1 - x*x/(float)(range*range));
6236 GL_Color(r, r, r, 1);
6237 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6238 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6239 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6240 GL_BlendFunc(GL_ONE, GL_ONE);
6243 // copy the vertically blurred bloom view to a texture
6244 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);
6245 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6249 void R_HDR_RenderBloomTexture(void)
6251 int oldwidth, oldheight;
6252 float oldcolorscale;
6253 qboolean oldwaterstate;
6255 oldwaterstate = r_waterstate.enabled;
6256 oldcolorscale = r_refdef.view.colorscale;
6257 oldwidth = r_refdef.view.width;
6258 oldheight = r_refdef.view.height;
6259 r_refdef.view.width = r_bloomstate.bloomwidth;
6260 r_refdef.view.height = r_bloomstate.bloomheight;
6262 if(r_hdr.integer < 2)
6263 r_waterstate.enabled = false;
6265 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6266 // TODO: add exposure compensation features
6267 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6269 r_refdef.view.showdebug = false;
6270 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6272 R_ResetViewRendering3D();
6274 R_ClearScreen(r_refdef.fogenabled);
6275 if (r_timereport_active)
6276 R_TimeReport("HDRclear");
6279 if (r_timereport_active)
6280 R_TimeReport("visibility");
6282 // only do secondary renders with HDR if r_hdr is 2 or higher
6283 r_waterstate.numwaterplanes = 0;
6284 if (r_waterstate.enabled)
6285 R_RenderWaterPlanes();
6287 r_refdef.view.showdebug = true;
6289 r_waterstate.numwaterplanes = 0;
6291 R_ResetViewRendering2D();
6293 R_Bloom_CopyHDRTexture();
6294 R_Bloom_MakeTexture();
6296 // restore the view settings
6297 r_waterstate.enabled = oldwaterstate;
6298 r_refdef.view.width = oldwidth;
6299 r_refdef.view.height = oldheight;
6300 r_refdef.view.colorscale = oldcolorscale;
6302 R_ResetViewRendering3D();
6304 R_ClearScreen(r_refdef.fogenabled);
6305 if (r_timereport_active)
6306 R_TimeReport("viewclear");
6309 static void R_BlendView(void)
6311 unsigned int permutation;
6312 float uservecs[4][4];
6314 switch (vid.renderpath)
6316 case RENDERPATH_GL20:
6317 case RENDERPATH_D3D9:
6318 case RENDERPATH_D3D10:
6319 case RENDERPATH_D3D11:
6320 case RENDERPATH_SOFT:
6321 case RENDERPATH_GLES2:
6323 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6324 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6325 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6326 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6327 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6329 if (r_bloomstate.texture_screen)
6331 // make sure the buffer is available
6332 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6334 R_ResetViewRendering2D();
6335 R_Mesh_SetMainRenderTargets();
6337 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6339 // declare variables
6340 float blur_factor, blur_mouseaccel, blur_velocity;
6341 static float blur_average;
6342 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6344 // set a goal for the factoring
6345 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6346 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6347 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6348 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6349 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6350 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6352 // from the goal, pick an averaged value between goal and last value
6353 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6354 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6356 // enforce minimum amount of blur
6357 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6359 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6361 // calculate values into a standard alpha
6362 cl.motionbluralpha = 1 - exp(-
6364 (r_motionblur.value * blur_factor / 80)
6366 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6369 max(0.0001, cl.time - cl.oldtime) // fps independent
6372 // randomization for the blur value to combat persistent ghosting
6373 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6374 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6377 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6379 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6380 GL_Color(1, 1, 1, cl.motionbluralpha);
6381 switch(vid.renderpath)
6383 case RENDERPATH_GL11:
6384 case RENDERPATH_GL13:
6385 case RENDERPATH_GL20:
6386 case RENDERPATH_GLES1:
6387 case RENDERPATH_GLES2:
6388 case RENDERPATH_SOFT:
6389 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6391 case RENDERPATH_D3D9:
6392 case RENDERPATH_D3D10:
6393 case RENDERPATH_D3D11:
6394 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6397 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6398 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6399 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6402 // updates old view angles for next pass
6403 VectorCopy(cl.viewangles, blur_oldangles);
6406 // copy view into the screen texture
6407 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);
6408 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6410 else if (!r_bloomstate.texture_bloom)
6412 // we may still have to do view tint...
6413 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6415 // apply a color tint to the whole view
6416 R_ResetViewRendering2D();
6417 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6418 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6419 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6420 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6421 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6423 break; // no screen processing, no bloom, skip it
6426 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6428 // render simple bloom effect
6429 // copy the screen and shrink it and darken it for the bloom process
6430 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6431 // make the bloom texture
6432 R_Bloom_MakeTexture();
6435 #if _MSC_VER >= 1400
6436 #define sscanf sscanf_s
6438 memset(uservecs, 0, sizeof(uservecs));
6439 if (r_glsl_postprocess_uservec1_enable.integer)
6440 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6441 if (r_glsl_postprocess_uservec2_enable.integer)
6442 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6443 if (r_glsl_postprocess_uservec3_enable.integer)
6444 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6445 if (r_glsl_postprocess_uservec4_enable.integer)
6446 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6448 R_ResetViewRendering2D();
6449 GL_Color(1, 1, 1, 1);
6450 GL_BlendFunc(GL_ONE, GL_ZERO);
6452 switch(vid.renderpath)
6454 case RENDERPATH_GL20:
6455 case RENDERPATH_GLES2:
6456 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6457 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6458 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6459 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6460 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6461 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]);
6462 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6463 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]);
6464 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]);
6465 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]);
6466 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]);
6467 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6468 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6469 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);
6471 case RENDERPATH_D3D9:
6473 // 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...
6474 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6475 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6476 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6477 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6478 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6479 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6480 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6481 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6482 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6483 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6484 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6485 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6486 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6487 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6490 case RENDERPATH_D3D10:
6491 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6493 case RENDERPATH_D3D11:
6494 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6496 case RENDERPATH_SOFT:
6497 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6498 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6499 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6500 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6501 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6502 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6503 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6504 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6505 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6506 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6507 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6508 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6509 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6510 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6515 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6516 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6518 case RENDERPATH_GL11:
6519 case RENDERPATH_GL13:
6520 case RENDERPATH_GLES1:
6521 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6523 // apply a color tint to the whole view
6524 R_ResetViewRendering2D();
6525 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6526 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6527 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6528 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6529 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6535 matrix4x4_t r_waterscrollmatrix;
6537 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6540 if (gamemode == GAME_NEHAHRA)
6542 if (gl_fogenable.integer)
6544 r_refdef.oldgl_fogenable = true;
6545 r_refdef.fog_density = gl_fogdensity.value;
6546 r_refdef.fog_red = gl_fogred.value;
6547 r_refdef.fog_green = gl_foggreen.value;
6548 r_refdef.fog_blue = gl_fogblue.value;
6549 r_refdef.fog_alpha = 1;
6550 r_refdef.fog_start = 0;
6551 r_refdef.fog_end = gl_skyclip.value;
6552 r_refdef.fog_height = 1<<30;
6553 r_refdef.fog_fadedepth = 128;
6555 else if (r_refdef.oldgl_fogenable)
6557 r_refdef.oldgl_fogenable = false;
6558 r_refdef.fog_density = 0;
6559 r_refdef.fog_red = 0;
6560 r_refdef.fog_green = 0;
6561 r_refdef.fog_blue = 0;
6562 r_refdef.fog_alpha = 0;
6563 r_refdef.fog_start = 0;
6564 r_refdef.fog_end = 0;
6565 r_refdef.fog_height = 1<<30;
6566 r_refdef.fog_fadedepth = 128;
6571 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6572 r_refdef.fog_start = max(0, r_refdef.fog_start);
6573 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6575 if (r_refdef.fog_density && r_drawfog.integer)
6577 r_refdef.fogenabled = true;
6578 // this is the point where the fog reaches 0.9986 alpha, which we
6579 // consider a good enough cutoff point for the texture
6580 // (0.9986 * 256 == 255.6)
6581 if (r_fog_exp2.integer)
6582 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6584 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6585 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6586 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6587 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6588 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6589 R_BuildFogHeightTexture();
6590 // fog color was already set
6591 // update the fog texture
6592 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)
6593 R_BuildFogTexture();
6594 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6595 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6598 r_refdef.fogenabled = false;
6601 if (r_refdef.fog_density)
6603 r_refdef.fogcolor[0] = r_refdef.fog_red;
6604 r_refdef.fogcolor[1] = r_refdef.fog_green;
6605 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6607 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6608 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6609 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6610 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6614 VectorCopy(r_refdef.fogcolor, fogvec);
6615 // color.rgb *= ContrastBoost * SceneBrightness;
6616 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6617 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6618 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6619 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6624 void R_UpdateVariables(void)
6628 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6630 r_refdef.farclip = r_farclip_base.value;
6631 if (r_refdef.scene.worldmodel)
6632 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6633 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6635 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6636 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6637 r_refdef.polygonfactor = 0;
6638 r_refdef.polygonoffset = 0;
6639 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6640 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6642 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6643 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6644 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6645 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6646 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6647 if (FAKELIGHT_ENABLED)
6649 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6651 if (r_showsurfaces.integer)
6653 r_refdef.scene.rtworld = false;
6654 r_refdef.scene.rtworldshadows = false;
6655 r_refdef.scene.rtdlight = false;
6656 r_refdef.scene.rtdlightshadows = false;
6657 r_refdef.lightmapintensity = 0;
6660 switch(vid.renderpath)
6662 case RENDERPATH_GL20:
6663 case RENDERPATH_D3D9:
6664 case RENDERPATH_D3D10:
6665 case RENDERPATH_D3D11:
6666 case RENDERPATH_SOFT:
6667 case RENDERPATH_GLES2:
6668 if(v_glslgamma.integer && !vid_gammatables_trivial)
6670 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6672 // build GLSL gamma texture
6673 #define RAMPWIDTH 256
6674 unsigned short ramp[RAMPWIDTH * 3];
6675 unsigned char rampbgr[RAMPWIDTH][4];
6678 r_texture_gammaramps_serial = vid_gammatables_serial;
6680 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6681 for(i = 0; i < RAMPWIDTH; ++i)
6683 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6684 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6685 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6688 if (r_texture_gammaramps)
6690 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6694 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6700 // remove GLSL gamma texture
6703 case RENDERPATH_GL11:
6704 case RENDERPATH_GL13:
6705 case RENDERPATH_GLES1:
6710 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6711 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6717 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6718 if( scenetype != r_currentscenetype ) {
6719 // store the old scenetype
6720 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6721 r_currentscenetype = scenetype;
6722 // move in the new scene
6723 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6732 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6734 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6735 if( scenetype == r_currentscenetype ) {
6736 return &r_refdef.scene;
6738 return &r_scenes_store[ scenetype ];
6742 int R_SortEntities_Compare(const void *ap, const void *bp)
6744 const entity_render_t *a = *(const entity_render_t **)ap;
6745 const entity_render_t *b = *(const entity_render_t **)bp;
6748 if(a->model < b->model)
6750 if(a->model > b->model)
6754 // TODO possibly calculate the REAL skinnum here first using
6756 if(a->skinnum < b->skinnum)
6758 if(a->skinnum > b->skinnum)
6761 // everything we compared is equal
6764 void R_SortEntities(void)
6766 // below or equal 2 ents, sorting never gains anything
6767 if(r_refdef.scene.numentities <= 2)
6770 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6778 int dpsoftrast_test;
6779 extern void R_Shadow_UpdateBounceGridTexture(void);
6780 extern cvar_t r_shadow_bouncegrid;
6781 void R_RenderView(void)
6783 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6785 dpsoftrast_test = r_test.integer;
6787 if (r_timereport_active)
6788 R_TimeReport("start");
6789 r_textureframe++; // used only by R_GetCurrentTexture
6790 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6792 if(R_CompileShader_CheckStaticParms())
6795 if (!r_drawentities.integer)
6796 r_refdef.scene.numentities = 0;
6797 else if (r_sortentities.integer)
6800 R_AnimCache_ClearCache();
6801 R_FrameData_NewFrame();
6803 /* adjust for stereo display */
6804 if(R_Stereo_Active())
6806 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);
6807 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6810 if (r_refdef.view.isoverlay)
6812 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6813 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6814 R_TimeReport("depthclear");
6816 r_refdef.view.showdebug = false;
6818 r_waterstate.enabled = false;
6819 r_waterstate.numwaterplanes = 0;
6823 r_refdef.view.matrix = originalmatrix;
6829 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6831 r_refdef.view.matrix = originalmatrix;
6832 return; //Host_Error ("R_RenderView: NULL worldmodel");
6835 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6837 R_RenderView_UpdateViewVectors();
6839 R_Shadow_UpdateWorldLightSelection();
6841 R_Bloom_StartFrame();
6842 R_Water_StartFrame();
6845 if (r_timereport_active)
6846 R_TimeReport("viewsetup");
6848 R_ResetViewRendering3D();
6850 if (r_refdef.view.clear || r_refdef.fogenabled)
6852 R_ClearScreen(r_refdef.fogenabled);
6853 if (r_timereport_active)
6854 R_TimeReport("viewclear");
6856 r_refdef.view.clear = true;
6858 // this produces a bloom texture to be used in R_BlendView() later
6859 if (r_bloomstate.hdr)
6861 R_HDR_RenderBloomTexture();
6862 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6863 r_textureframe++; // used only by R_GetCurrentTexture
6866 r_refdef.view.showdebug = true;
6869 if (r_timereport_active)
6870 R_TimeReport("visibility");
6872 R_Shadow_UpdateBounceGridTexture();
6873 if (r_timereport_active && r_shadow_bouncegrid.integer)
6874 R_TimeReport("bouncegrid");
6876 r_waterstate.numwaterplanes = 0;
6877 if (r_waterstate.enabled)
6878 R_RenderWaterPlanes();
6881 r_waterstate.numwaterplanes = 0;
6884 if (r_timereport_active)
6885 R_TimeReport("blendview");
6887 GL_Scissor(0, 0, vid.width, vid.height);
6888 GL_ScissorTest(false);
6890 r_refdef.view.matrix = originalmatrix;
6895 void R_RenderWaterPlanes(void)
6897 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6899 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6900 if (r_timereport_active)
6901 R_TimeReport("waterworld");
6904 // don't let sound skip if going slow
6905 if (r_refdef.scene.extraupdate)
6908 R_DrawModelsAddWaterPlanes();
6909 if (r_timereport_active)
6910 R_TimeReport("watermodels");
6912 if (r_waterstate.numwaterplanes)
6914 R_Water_ProcessPlanes();
6915 if (r_timereport_active)
6916 R_TimeReport("waterscenes");
6920 extern void R_DrawLightningBeams (void);
6921 extern void VM_CL_AddPolygonsToMeshQueue (void);
6922 extern void R_DrawPortals (void);
6923 extern cvar_t cl_locs_show;
6924 static void R_DrawLocs(void);
6925 static void R_DrawEntityBBoxes(void);
6926 static void R_DrawModelDecals(void);
6927 extern void R_DrawModelShadows(void);
6928 extern void R_DrawModelShadowMaps(void);
6929 extern cvar_t cl_decals_newsystem;
6930 extern qboolean r_shadow_usingdeferredprepass;
6931 void R_RenderScene(void)
6933 qboolean shadowmapping = false;
6935 if (r_timereport_active)
6936 R_TimeReport("beginscene");
6938 r_refdef.stats.renders++;
6942 // don't let sound skip if going slow
6943 if (r_refdef.scene.extraupdate)
6946 R_MeshQueue_BeginScene();
6950 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);
6952 if (r_timereport_active)
6953 R_TimeReport("skystartframe");
6955 if (cl.csqc_vidvars.drawworld)
6957 // don't let sound skip if going slow
6958 if (r_refdef.scene.extraupdate)
6961 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6963 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6964 if (r_timereport_active)
6965 R_TimeReport("worldsky");
6968 if (R_DrawBrushModelsSky() && r_timereport_active)
6969 R_TimeReport("bmodelsky");
6971 if (skyrendermasked && skyrenderlater)
6973 // we have to force off the water clipping plane while rendering sky
6977 if (r_timereport_active)
6978 R_TimeReport("sky");
6982 R_AnimCache_CacheVisibleEntities();
6983 if (r_timereport_active)
6984 R_TimeReport("animation");
6986 R_Shadow_PrepareLights();
6987 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6988 R_Shadow_PrepareModelShadows();
6989 if (r_timereport_active)
6990 R_TimeReport("preparelights");
6992 if (R_Shadow_ShadowMappingEnabled())
6993 shadowmapping = true;
6995 if (r_shadow_usingdeferredprepass)
6996 R_Shadow_DrawPrepass();
6998 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7000 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7001 if (r_timereport_active)
7002 R_TimeReport("worlddepth");
7004 if (r_depthfirst.integer >= 2)
7006 R_DrawModelsDepth();
7007 if (r_timereport_active)
7008 R_TimeReport("modeldepth");
7011 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7013 R_DrawModelShadowMaps();
7014 R_ResetViewRendering3D();
7015 // don't let sound skip if going slow
7016 if (r_refdef.scene.extraupdate)
7020 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7022 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7023 if (r_timereport_active)
7024 R_TimeReport("world");
7027 // don't let sound skip if going slow
7028 if (r_refdef.scene.extraupdate)
7032 if (r_timereport_active)
7033 R_TimeReport("models");
7035 // don't let sound skip if going slow
7036 if (r_refdef.scene.extraupdate)
7039 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7041 R_DrawModelShadows();
7042 R_ResetViewRendering3D();
7043 // don't let sound skip if going slow
7044 if (r_refdef.scene.extraupdate)
7048 if (!r_shadow_usingdeferredprepass)
7050 R_Shadow_DrawLights();
7051 if (r_timereport_active)
7052 R_TimeReport("rtlights");
7055 // don't let sound skip if going slow
7056 if (r_refdef.scene.extraupdate)
7059 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7061 R_DrawModelShadows();
7062 R_ResetViewRendering3D();
7063 // don't let sound skip if going slow
7064 if (r_refdef.scene.extraupdate)
7068 if (cl.csqc_vidvars.drawworld)
7070 if (cl_decals_newsystem.integer)
7072 R_DrawModelDecals();
7073 if (r_timereport_active)
7074 R_TimeReport("modeldecals");
7079 if (r_timereport_active)
7080 R_TimeReport("decals");
7084 if (r_timereport_active)
7085 R_TimeReport("particles");
7088 if (r_timereport_active)
7089 R_TimeReport("explosions");
7091 R_DrawLightningBeams();
7092 if (r_timereport_active)
7093 R_TimeReport("lightning");
7096 VM_CL_AddPolygonsToMeshQueue();
7098 if (r_refdef.view.showdebug)
7100 if (cl_locs_show.integer)
7103 if (r_timereport_active)
7104 R_TimeReport("showlocs");
7107 if (r_drawportals.integer)
7110 if (r_timereport_active)
7111 R_TimeReport("portals");
7114 if (r_showbboxes.value > 0)
7116 R_DrawEntityBBoxes();
7117 if (r_timereport_active)
7118 R_TimeReport("bboxes");
7122 if (r_transparent.integer)
7124 R_MeshQueue_RenderTransparent();
7125 if (r_timereport_active)
7126 R_TimeReport("drawtrans");
7129 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))
7131 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7132 if (r_timereport_active)
7133 R_TimeReport("worlddebug");
7134 R_DrawModelsDebug();
7135 if (r_timereport_active)
7136 R_TimeReport("modeldebug");
7139 if (cl.csqc_vidvars.drawworld)
7141 R_Shadow_DrawCoronas();
7142 if (r_timereport_active)
7143 R_TimeReport("coronas");
7148 GL_DepthTest(false);
7149 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7150 GL_Color(1, 1, 1, 1);
7151 qglBegin(GL_POLYGON);
7152 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7153 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7154 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7155 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7157 qglBegin(GL_POLYGON);
7158 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]);
7159 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]);
7160 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]);
7161 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]);
7163 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7167 // don't let sound skip if going slow
7168 if (r_refdef.scene.extraupdate)
7171 R_ResetViewRendering2D();
7174 static const unsigned short bboxelements[36] =
7184 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7187 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7189 RSurf_ActiveWorldEntity();
7191 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7192 GL_DepthMask(false);
7193 GL_DepthRange(0, 1);
7194 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7195 // R_Mesh_ResetTextureState();
7197 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7198 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7199 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7200 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7201 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7202 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7203 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7204 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7205 R_FillColors(color4f, 8, cr, cg, cb, ca);
7206 if (r_refdef.fogenabled)
7208 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7210 f1 = RSurf_FogVertex(v);
7212 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7213 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7214 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7217 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7218 R_Mesh_ResetTextureState();
7219 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7220 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7223 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7227 prvm_edict_t *edict;
7228 prvm_prog_t *prog_save = prog;
7230 // this function draws bounding boxes of server entities
7234 GL_CullFace(GL_NONE);
7235 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7239 for (i = 0;i < numsurfaces;i++)
7241 edict = PRVM_EDICT_NUM(surfacelist[i]);
7242 switch ((int)PRVM_serveredictfloat(edict, solid))
7244 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7245 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7246 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7247 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7248 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7249 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7251 color[3] *= r_showbboxes.value;
7252 color[3] = bound(0, color[3], 1);
7253 GL_DepthTest(!r_showdisabledepthtest.integer);
7254 GL_CullFace(r_refdef.view.cullface_front);
7255 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7261 static void R_DrawEntityBBoxes(void)
7264 prvm_edict_t *edict;
7266 prvm_prog_t *prog_save = prog;
7268 // this function draws bounding boxes of server entities
7274 for (i = 0;i < prog->num_edicts;i++)
7276 edict = PRVM_EDICT_NUM(i);
7277 if (edict->priv.server->free)
7279 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7280 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7282 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7284 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7285 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7291 static const int nomodelelement3i[24] =
7303 static const unsigned short nomodelelement3s[24] =
7315 static const float nomodelvertex3f[6*3] =
7325 static const float nomodelcolor4f[6*4] =
7327 0.0f, 0.0f, 0.5f, 1.0f,
7328 0.0f, 0.0f, 0.5f, 1.0f,
7329 0.0f, 0.5f, 0.0f, 1.0f,
7330 0.0f, 0.5f, 0.0f, 1.0f,
7331 0.5f, 0.0f, 0.0f, 1.0f,
7332 0.5f, 0.0f, 0.0f, 1.0f
7335 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7341 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);
7343 // this is only called once per entity so numsurfaces is always 1, and
7344 // surfacelist is always {0}, so this code does not handle batches
7346 if (rsurface.ent_flags & RENDER_ADDITIVE)
7348 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7349 GL_DepthMask(false);
7351 else if (rsurface.colormod[3] < 1)
7353 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7354 GL_DepthMask(false);
7358 GL_BlendFunc(GL_ONE, GL_ZERO);
7361 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7362 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7363 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7364 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7365 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7366 for (i = 0, c = color4f;i < 6;i++, c += 4)
7368 c[0] *= rsurface.colormod[0];
7369 c[1] *= rsurface.colormod[1];
7370 c[2] *= rsurface.colormod[2];
7371 c[3] *= rsurface.colormod[3];
7373 if (r_refdef.fogenabled)
7375 for (i = 0, c = color4f;i < 6;i++, c += 4)
7377 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7379 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7380 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7381 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7384 // R_Mesh_ResetTextureState();
7385 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7386 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7387 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7390 void R_DrawNoModel(entity_render_t *ent)
7393 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7394 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7395 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7397 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7400 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7402 vec3_t right1, right2, diff, normal;
7404 VectorSubtract (org2, org1, normal);
7406 // calculate 'right' vector for start
7407 VectorSubtract (r_refdef.view.origin, org1, diff);
7408 CrossProduct (normal, diff, right1);
7409 VectorNormalize (right1);
7411 // calculate 'right' vector for end
7412 VectorSubtract (r_refdef.view.origin, org2, diff);
7413 CrossProduct (normal, diff, right2);
7414 VectorNormalize (right2);
7416 vert[ 0] = org1[0] + width * right1[0];
7417 vert[ 1] = org1[1] + width * right1[1];
7418 vert[ 2] = org1[2] + width * right1[2];
7419 vert[ 3] = org1[0] - width * right1[0];
7420 vert[ 4] = org1[1] - width * right1[1];
7421 vert[ 5] = org1[2] - width * right1[2];
7422 vert[ 6] = org2[0] - width * right2[0];
7423 vert[ 7] = org2[1] - width * right2[1];
7424 vert[ 8] = org2[2] - width * right2[2];
7425 vert[ 9] = org2[0] + width * right2[0];
7426 vert[10] = org2[1] + width * right2[1];
7427 vert[11] = org2[2] + width * right2[2];
7430 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)
7432 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7433 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7434 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7435 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7436 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7437 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7438 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7439 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7440 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7441 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7442 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7443 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7446 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7451 VectorSet(v, x, y, z);
7452 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7453 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7455 if (i == mesh->numvertices)
7457 if (mesh->numvertices < mesh->maxvertices)
7459 VectorCopy(v, vertex3f);
7460 mesh->numvertices++;
7462 return mesh->numvertices;
7468 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7472 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7473 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7474 e = mesh->element3i + mesh->numtriangles * 3;
7475 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7477 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7478 if (mesh->numtriangles < mesh->maxtriangles)
7483 mesh->numtriangles++;
7485 element[1] = element[2];
7489 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7493 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7494 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7495 e = mesh->element3i + mesh->numtriangles * 3;
7496 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7498 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7499 if (mesh->numtriangles < mesh->maxtriangles)
7504 mesh->numtriangles++;
7506 element[1] = element[2];
7510 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7511 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7513 int planenum, planenum2;
7516 mplane_t *plane, *plane2;
7518 double temppoints[2][256*3];
7519 // figure out how large a bounding box we need to properly compute this brush
7521 for (w = 0;w < numplanes;w++)
7522 maxdist = max(maxdist, fabs(planes[w].dist));
7523 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7524 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7525 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7529 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7530 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7532 if (planenum2 == planenum)
7534 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);
7537 if (tempnumpoints < 3)
7539 // generate elements forming a triangle fan for this polygon
7540 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7544 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)
7546 texturelayer_t *layer;
7547 layer = t->currentlayers + t->currentnumlayers++;
7549 layer->depthmask = depthmask;
7550 layer->blendfunc1 = blendfunc1;
7551 layer->blendfunc2 = blendfunc2;
7552 layer->texture = texture;
7553 layer->texmatrix = *matrix;
7554 layer->color[0] = r;
7555 layer->color[1] = g;
7556 layer->color[2] = b;
7557 layer->color[3] = a;
7560 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7562 if(parms[0] == 0 && parms[1] == 0)
7564 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7565 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7570 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7573 index = parms[2] + rsurface.shadertime * parms[3];
7574 index -= floor(index);
7575 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7578 case Q3WAVEFUNC_NONE:
7579 case Q3WAVEFUNC_NOISE:
7580 case Q3WAVEFUNC_COUNT:
7583 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7584 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7585 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7586 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7587 case Q3WAVEFUNC_TRIANGLE:
7589 f = index - floor(index);
7602 f = parms[0] + parms[1] * f;
7603 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7604 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7608 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7614 matrix4x4_t matrix, temp;
7615 switch(tcmod->tcmod)
7619 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7620 matrix = r_waterscrollmatrix;
7622 matrix = identitymatrix;
7624 case Q3TCMOD_ENTITYTRANSLATE:
7625 // this is used in Q3 to allow the gamecode to control texcoord
7626 // scrolling on the entity, which is not supported in darkplaces yet.
7627 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7629 case Q3TCMOD_ROTATE:
7630 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7631 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7632 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7635 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7637 case Q3TCMOD_SCROLL:
7638 // extra care is needed because of precision breakdown with large values of time
7639 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7640 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7641 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7643 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7644 w = (int) tcmod->parms[0];
7645 h = (int) tcmod->parms[1];
7646 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7648 idx = (int) floor(f * w * h);
7649 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7651 case Q3TCMOD_STRETCH:
7652 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7653 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7655 case Q3TCMOD_TRANSFORM:
7656 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7657 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7658 VectorSet(tcmat + 6, 0 , 0 , 1);
7659 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7660 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7662 case Q3TCMOD_TURBULENT:
7663 // this is handled in the RSurf_PrepareVertices function
7664 matrix = identitymatrix;
7668 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7671 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7673 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7674 char name[MAX_QPATH];
7675 skinframe_t *skinframe;
7676 unsigned char pixels[296*194];
7677 strlcpy(cache->name, skinname, sizeof(cache->name));
7678 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7679 if (developer_loading.integer)
7680 Con_Printf("loading %s\n", name);
7681 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7682 if (!skinframe || !skinframe->base)
7685 fs_offset_t filesize;
7687 f = FS_LoadFile(name, tempmempool, true, &filesize);
7690 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7691 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7695 cache->skinframe = skinframe;
7698 texture_t *R_GetCurrentTexture(texture_t *t)
7701 const entity_render_t *ent = rsurface.entity;
7702 dp_model_t *model = ent->model;
7703 q3shaderinfo_layer_tcmod_t *tcmod;
7705 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7706 return t->currentframe;
7707 t->update_lastrenderframe = r_textureframe;
7708 t->update_lastrenderentity = (void *)ent;
7710 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7711 t->camera_entity = ent->entitynumber;
7713 t->camera_entity = 0;
7715 // switch to an alternate material if this is a q1bsp animated material
7717 texture_t *texture = t;
7718 int s = rsurface.ent_skinnum;
7719 if ((unsigned int)s >= (unsigned int)model->numskins)
7721 if (model->skinscenes)
7723 if (model->skinscenes[s].framecount > 1)
7724 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7726 s = model->skinscenes[s].firstframe;
7729 t = t + s * model->num_surfaces;
7732 // use an alternate animation if the entity's frame is not 0,
7733 // and only if the texture has an alternate animation
7734 if (rsurface.ent_alttextures && t->anim_total[1])
7735 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7737 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7739 texture->currentframe = t;
7742 // update currentskinframe to be a qw skin or animation frame
7743 if (rsurface.ent_qwskin >= 0)
7745 i = rsurface.ent_qwskin;
7746 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7748 r_qwskincache_size = cl.maxclients;
7750 Mem_Free(r_qwskincache);
7751 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7753 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7754 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7755 t->currentskinframe = r_qwskincache[i].skinframe;
7756 if (t->currentskinframe == NULL)
7757 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7759 else if (t->numskinframes >= 2)
7760 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7761 if (t->backgroundnumskinframes >= 2)
7762 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7764 t->currentmaterialflags = t->basematerialflags;
7765 t->currentalpha = rsurface.colormod[3];
7766 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7767 t->currentalpha *= r_wateralpha.value;
7768 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7769 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7770 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7771 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7772 if (!(rsurface.ent_flags & RENDER_LIGHT))
7773 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7774 else if (FAKELIGHT_ENABLED)
7776 // no modellight if using fakelight for the map
7778 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7780 // pick a model lighting mode
7781 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7782 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7784 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7786 if (rsurface.ent_flags & RENDER_ADDITIVE)
7787 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7788 else if (t->currentalpha < 1)
7789 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7790 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7791 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7792 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7793 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7794 if (t->backgroundnumskinframes)
7795 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7796 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7798 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7799 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7802 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7803 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7805 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7806 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7808 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7809 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7811 // there is no tcmod
7812 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7814 t->currenttexmatrix = r_waterscrollmatrix;
7815 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7817 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7819 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7820 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7823 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7824 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7825 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7826 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7828 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7829 if (t->currentskinframe->qpixels)
7830 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7831 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7832 if (!t->basetexture)
7833 t->basetexture = r_texture_notexture;
7834 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7835 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7836 t->nmaptexture = t->currentskinframe->nmap;
7837 if (!t->nmaptexture)
7838 t->nmaptexture = r_texture_blanknormalmap;
7839 t->glosstexture = r_texture_black;
7840 t->glowtexture = t->currentskinframe->glow;
7841 t->fogtexture = t->currentskinframe->fog;
7842 t->reflectmasktexture = t->currentskinframe->reflect;
7843 if (t->backgroundnumskinframes)
7845 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7846 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7847 t->backgroundglosstexture = r_texture_black;
7848 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7849 if (!t->backgroundnmaptexture)
7850 t->backgroundnmaptexture = r_texture_blanknormalmap;
7854 t->backgroundbasetexture = r_texture_white;
7855 t->backgroundnmaptexture = r_texture_blanknormalmap;
7856 t->backgroundglosstexture = r_texture_black;
7857 t->backgroundglowtexture = NULL;
7859 t->specularpower = r_shadow_glossexponent.value;
7860 // TODO: store reference values for these in the texture?
7861 t->specularscale = 0;
7862 if (r_shadow_gloss.integer > 0)
7864 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7866 if (r_shadow_glossintensity.value > 0)
7868 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7869 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7870 t->specularscale = r_shadow_glossintensity.value;
7873 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7875 t->glosstexture = r_texture_white;
7876 t->backgroundglosstexture = r_texture_white;
7877 t->specularscale = r_shadow_gloss2intensity.value;
7878 t->specularpower = r_shadow_gloss2exponent.value;
7881 t->specularscale *= t->specularscalemod;
7882 t->specularpower *= t->specularpowermod;
7884 // lightmaps mode looks bad with dlights using actual texturing, so turn
7885 // off the colormap and glossmap, but leave the normalmap on as it still
7886 // accurately represents the shading involved
7887 if (gl_lightmaps.integer)
7889 t->basetexture = r_texture_grey128;
7890 t->pantstexture = r_texture_black;
7891 t->shirttexture = r_texture_black;
7892 t->nmaptexture = r_texture_blanknormalmap;
7893 t->glosstexture = r_texture_black;
7894 t->glowtexture = NULL;
7895 t->fogtexture = NULL;
7896 t->reflectmasktexture = NULL;
7897 t->backgroundbasetexture = NULL;
7898 t->backgroundnmaptexture = r_texture_blanknormalmap;
7899 t->backgroundglosstexture = r_texture_black;
7900 t->backgroundglowtexture = NULL;
7901 t->specularscale = 0;
7902 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7905 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7906 VectorClear(t->dlightcolor);
7907 t->currentnumlayers = 0;
7908 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7910 int blendfunc1, blendfunc2;
7912 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7914 blendfunc1 = GL_SRC_ALPHA;
7915 blendfunc2 = GL_ONE;
7917 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7919 blendfunc1 = GL_SRC_ALPHA;
7920 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7922 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7924 blendfunc1 = t->customblendfunc[0];
7925 blendfunc2 = t->customblendfunc[1];
7929 blendfunc1 = GL_ONE;
7930 blendfunc2 = GL_ZERO;
7932 // don't colormod evilblend textures
7933 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7934 VectorSet(t->lightmapcolor, 1, 1, 1);
7935 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7936 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7938 // fullbright is not affected by r_refdef.lightmapintensity
7939 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]);
7940 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7941 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]);
7942 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7943 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]);
7947 vec3_t ambientcolor;
7949 // set the color tint used for lights affecting this surface
7950 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7952 // q3bsp has no lightmap updates, so the lightstylevalue that
7953 // would normally be baked into the lightmap must be
7954 // applied to the color
7955 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7956 if (model->type == mod_brushq3)
7957 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7958 colorscale *= r_refdef.lightmapintensity;
7959 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7960 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7961 // basic lit geometry
7962 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]);
7963 // add pants/shirt if needed
7964 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7965 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]);
7966 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7967 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]);
7968 // now add ambient passes if needed
7969 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7971 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]);
7972 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7973 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]);
7974 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7975 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]);
7978 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7979 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]);
7980 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7982 // if this is opaque use alpha blend which will darken the earlier
7985 // if this is an alpha blended material, all the earlier passes
7986 // were darkened by fog already, so we only need to add the fog
7987 // color ontop through the fog mask texture
7989 // if this is an additive blended material, all the earlier passes
7990 // were darkened by fog already, and we should not add fog color
7991 // (because the background was not darkened, there is no fog color
7992 // that was lost behind it).
7993 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]);
7997 return t->currentframe;
8000 rsurfacestate_t rsurface;
8002 void RSurf_ActiveWorldEntity(void)
8004 dp_model_t *model = r_refdef.scene.worldmodel;
8005 //if (rsurface.entity == r_refdef.scene.worldentity)
8007 rsurface.entity = r_refdef.scene.worldentity;
8008 rsurface.skeleton = NULL;
8009 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8010 rsurface.ent_skinnum = 0;
8011 rsurface.ent_qwskin = -1;
8012 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8013 rsurface.shadertime = r_refdef.scene.time;
8014 rsurface.matrix = identitymatrix;
8015 rsurface.inversematrix = identitymatrix;
8016 rsurface.matrixscale = 1;
8017 rsurface.inversematrixscale = 1;
8018 R_EntityMatrix(&identitymatrix);
8019 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8020 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8021 rsurface.fograngerecip = r_refdef.fograngerecip;
8022 rsurface.fogheightfade = r_refdef.fogheightfade;
8023 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8024 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8025 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8026 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8027 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8028 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8029 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8030 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8031 rsurface.colormod[3] = 1;
8032 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);
8033 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8034 rsurface.frameblend[0].lerp = 1;
8035 rsurface.ent_alttextures = false;
8036 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8037 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8038 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8039 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8040 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8041 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8042 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8043 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8044 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8045 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8046 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8047 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8048 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8049 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8050 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8051 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8052 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8053 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8054 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8055 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8056 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8057 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8058 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8059 rsurface.modelelement3i = model->surfmesh.data_element3i;
8060 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8061 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8062 rsurface.modelelement3s = model->surfmesh.data_element3s;
8063 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8064 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8065 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8066 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8067 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8068 rsurface.modelsurfaces = model->data_surfaces;
8069 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8070 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8071 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8072 rsurface.modelgeneratedvertex = false;
8073 rsurface.batchgeneratedvertex = false;
8074 rsurface.batchfirstvertex = 0;
8075 rsurface.batchnumvertices = 0;
8076 rsurface.batchfirsttriangle = 0;
8077 rsurface.batchnumtriangles = 0;
8078 rsurface.batchvertex3f = NULL;
8079 rsurface.batchvertex3f_vertexbuffer = NULL;
8080 rsurface.batchvertex3f_bufferoffset = 0;
8081 rsurface.batchsvector3f = NULL;
8082 rsurface.batchsvector3f_vertexbuffer = NULL;
8083 rsurface.batchsvector3f_bufferoffset = 0;
8084 rsurface.batchtvector3f = NULL;
8085 rsurface.batchtvector3f_vertexbuffer = NULL;
8086 rsurface.batchtvector3f_bufferoffset = 0;
8087 rsurface.batchnormal3f = NULL;
8088 rsurface.batchnormal3f_vertexbuffer = NULL;
8089 rsurface.batchnormal3f_bufferoffset = 0;
8090 rsurface.batchlightmapcolor4f = NULL;
8091 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8092 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8093 rsurface.batchtexcoordtexture2f = NULL;
8094 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8095 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8096 rsurface.batchtexcoordlightmap2f = NULL;
8097 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8098 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8099 rsurface.batchvertexmesh = NULL;
8100 rsurface.batchvertexmeshbuffer = NULL;
8101 rsurface.batchvertex3fbuffer = NULL;
8102 rsurface.batchelement3i = NULL;
8103 rsurface.batchelement3i_indexbuffer = NULL;
8104 rsurface.batchelement3i_bufferoffset = 0;
8105 rsurface.batchelement3s = NULL;
8106 rsurface.batchelement3s_indexbuffer = NULL;
8107 rsurface.batchelement3s_bufferoffset = 0;
8108 rsurface.passcolor4f = NULL;
8109 rsurface.passcolor4f_vertexbuffer = NULL;
8110 rsurface.passcolor4f_bufferoffset = 0;
8113 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8115 dp_model_t *model = ent->model;
8116 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8118 rsurface.entity = (entity_render_t *)ent;
8119 rsurface.skeleton = ent->skeleton;
8120 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8121 rsurface.ent_skinnum = ent->skinnum;
8122 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;
8123 rsurface.ent_flags = ent->flags;
8124 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8125 rsurface.matrix = ent->matrix;
8126 rsurface.inversematrix = ent->inversematrix;
8127 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8128 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8129 R_EntityMatrix(&rsurface.matrix);
8130 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8131 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8132 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8133 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8134 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8135 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8136 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8137 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8138 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8139 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8140 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8141 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8142 rsurface.colormod[3] = ent->alpha;
8143 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8144 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8145 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8146 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8147 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8148 if (ent->model->brush.submodel && !prepass)
8150 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8151 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8153 if (model->surfmesh.isanimated && model->AnimateVertices)
8155 if (ent->animcache_vertex3f)
8157 rsurface.modelvertex3f = ent->animcache_vertex3f;
8158 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8159 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8160 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8161 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8162 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8163 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8165 else if (wanttangents)
8167 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8168 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8169 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8170 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8171 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8172 rsurface.modelvertexmesh = NULL;
8173 rsurface.modelvertexmeshbuffer = NULL;
8174 rsurface.modelvertex3fbuffer = NULL;
8176 else if (wantnormals)
8178 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8179 rsurface.modelsvector3f = NULL;
8180 rsurface.modeltvector3f = NULL;
8181 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8182 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8183 rsurface.modelvertexmesh = NULL;
8184 rsurface.modelvertexmeshbuffer = NULL;
8185 rsurface.modelvertex3fbuffer = NULL;
8189 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8190 rsurface.modelsvector3f = NULL;
8191 rsurface.modeltvector3f = NULL;
8192 rsurface.modelnormal3f = NULL;
8193 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8194 rsurface.modelvertexmesh = NULL;
8195 rsurface.modelvertexmeshbuffer = NULL;
8196 rsurface.modelvertex3fbuffer = NULL;
8198 rsurface.modelvertex3f_vertexbuffer = 0;
8199 rsurface.modelvertex3f_bufferoffset = 0;
8200 rsurface.modelsvector3f_vertexbuffer = 0;
8201 rsurface.modelsvector3f_bufferoffset = 0;
8202 rsurface.modeltvector3f_vertexbuffer = 0;
8203 rsurface.modeltvector3f_bufferoffset = 0;
8204 rsurface.modelnormal3f_vertexbuffer = 0;
8205 rsurface.modelnormal3f_bufferoffset = 0;
8206 rsurface.modelgeneratedvertex = true;
8210 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8211 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8212 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8213 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8214 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8215 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8216 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8217 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8218 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8219 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8220 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8221 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8222 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8223 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8224 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8225 rsurface.modelgeneratedvertex = false;
8227 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8228 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8229 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8230 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8231 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8232 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8233 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8234 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8235 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8236 rsurface.modelelement3i = model->surfmesh.data_element3i;
8237 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8238 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8239 rsurface.modelelement3s = model->surfmesh.data_element3s;
8240 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8241 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8242 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8243 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8244 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8245 rsurface.modelsurfaces = model->data_surfaces;
8246 rsurface.batchgeneratedvertex = false;
8247 rsurface.batchfirstvertex = 0;
8248 rsurface.batchnumvertices = 0;
8249 rsurface.batchfirsttriangle = 0;
8250 rsurface.batchnumtriangles = 0;
8251 rsurface.batchvertex3f = NULL;
8252 rsurface.batchvertex3f_vertexbuffer = NULL;
8253 rsurface.batchvertex3f_bufferoffset = 0;
8254 rsurface.batchsvector3f = NULL;
8255 rsurface.batchsvector3f_vertexbuffer = NULL;
8256 rsurface.batchsvector3f_bufferoffset = 0;
8257 rsurface.batchtvector3f = NULL;
8258 rsurface.batchtvector3f_vertexbuffer = NULL;
8259 rsurface.batchtvector3f_bufferoffset = 0;
8260 rsurface.batchnormal3f = NULL;
8261 rsurface.batchnormal3f_vertexbuffer = NULL;
8262 rsurface.batchnormal3f_bufferoffset = 0;
8263 rsurface.batchlightmapcolor4f = NULL;
8264 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8265 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8266 rsurface.batchtexcoordtexture2f = NULL;
8267 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8268 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8269 rsurface.batchtexcoordlightmap2f = NULL;
8270 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8271 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8272 rsurface.batchvertexmesh = NULL;
8273 rsurface.batchvertexmeshbuffer = NULL;
8274 rsurface.batchvertex3fbuffer = NULL;
8275 rsurface.batchelement3i = NULL;
8276 rsurface.batchelement3i_indexbuffer = NULL;
8277 rsurface.batchelement3i_bufferoffset = 0;
8278 rsurface.batchelement3s = NULL;
8279 rsurface.batchelement3s_indexbuffer = NULL;
8280 rsurface.batchelement3s_bufferoffset = 0;
8281 rsurface.passcolor4f = NULL;
8282 rsurface.passcolor4f_vertexbuffer = NULL;
8283 rsurface.passcolor4f_bufferoffset = 0;
8286 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)
8288 rsurface.entity = r_refdef.scene.worldentity;
8289 rsurface.skeleton = NULL;
8290 rsurface.ent_skinnum = 0;
8291 rsurface.ent_qwskin = -1;
8292 rsurface.ent_flags = entflags;
8293 rsurface.shadertime = r_refdef.scene.time - shadertime;
8294 rsurface.modelnumvertices = numvertices;
8295 rsurface.modelnumtriangles = numtriangles;
8296 rsurface.matrix = *matrix;
8297 rsurface.inversematrix = *inversematrix;
8298 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8299 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8300 R_EntityMatrix(&rsurface.matrix);
8301 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8302 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8303 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8304 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8305 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8306 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8307 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8308 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8309 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8310 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8311 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8312 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8313 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);
8314 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8315 rsurface.frameblend[0].lerp = 1;
8316 rsurface.ent_alttextures = false;
8317 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8318 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8321 rsurface.modelvertex3f = (float *)vertex3f;
8322 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8323 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8324 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8326 else if (wantnormals)
8328 rsurface.modelvertex3f = (float *)vertex3f;
8329 rsurface.modelsvector3f = NULL;
8330 rsurface.modeltvector3f = NULL;
8331 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8335 rsurface.modelvertex3f = (float *)vertex3f;
8336 rsurface.modelsvector3f = NULL;
8337 rsurface.modeltvector3f = NULL;
8338 rsurface.modelnormal3f = NULL;
8340 rsurface.modelvertexmesh = NULL;
8341 rsurface.modelvertexmeshbuffer = NULL;
8342 rsurface.modelvertex3fbuffer = NULL;
8343 rsurface.modelvertex3f_vertexbuffer = 0;
8344 rsurface.modelvertex3f_bufferoffset = 0;
8345 rsurface.modelsvector3f_vertexbuffer = 0;
8346 rsurface.modelsvector3f_bufferoffset = 0;
8347 rsurface.modeltvector3f_vertexbuffer = 0;
8348 rsurface.modeltvector3f_bufferoffset = 0;
8349 rsurface.modelnormal3f_vertexbuffer = 0;
8350 rsurface.modelnormal3f_bufferoffset = 0;
8351 rsurface.modelgeneratedvertex = true;
8352 rsurface.modellightmapcolor4f = (float *)color4f;
8353 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8354 rsurface.modellightmapcolor4f_bufferoffset = 0;
8355 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8356 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8357 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8358 rsurface.modeltexcoordlightmap2f = NULL;
8359 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8360 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8361 rsurface.modelelement3i = (int *)element3i;
8362 rsurface.modelelement3i_indexbuffer = NULL;
8363 rsurface.modelelement3i_bufferoffset = 0;
8364 rsurface.modelelement3s = (unsigned short *)element3s;
8365 rsurface.modelelement3s_indexbuffer = NULL;
8366 rsurface.modelelement3s_bufferoffset = 0;
8367 rsurface.modellightmapoffsets = NULL;
8368 rsurface.modelsurfaces = NULL;
8369 rsurface.batchgeneratedvertex = false;
8370 rsurface.batchfirstvertex = 0;
8371 rsurface.batchnumvertices = 0;
8372 rsurface.batchfirsttriangle = 0;
8373 rsurface.batchnumtriangles = 0;
8374 rsurface.batchvertex3f = NULL;
8375 rsurface.batchvertex3f_vertexbuffer = NULL;
8376 rsurface.batchvertex3f_bufferoffset = 0;
8377 rsurface.batchsvector3f = NULL;
8378 rsurface.batchsvector3f_vertexbuffer = NULL;
8379 rsurface.batchsvector3f_bufferoffset = 0;
8380 rsurface.batchtvector3f = NULL;
8381 rsurface.batchtvector3f_vertexbuffer = NULL;
8382 rsurface.batchtvector3f_bufferoffset = 0;
8383 rsurface.batchnormal3f = NULL;
8384 rsurface.batchnormal3f_vertexbuffer = NULL;
8385 rsurface.batchnormal3f_bufferoffset = 0;
8386 rsurface.batchlightmapcolor4f = NULL;
8387 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8388 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8389 rsurface.batchtexcoordtexture2f = NULL;
8390 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8391 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8392 rsurface.batchtexcoordlightmap2f = NULL;
8393 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8394 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8395 rsurface.batchvertexmesh = NULL;
8396 rsurface.batchvertexmeshbuffer = NULL;
8397 rsurface.batchvertex3fbuffer = NULL;
8398 rsurface.batchelement3i = NULL;
8399 rsurface.batchelement3i_indexbuffer = NULL;
8400 rsurface.batchelement3i_bufferoffset = 0;
8401 rsurface.batchelement3s = NULL;
8402 rsurface.batchelement3s_indexbuffer = NULL;
8403 rsurface.batchelement3s_bufferoffset = 0;
8404 rsurface.passcolor4f = NULL;
8405 rsurface.passcolor4f_vertexbuffer = NULL;
8406 rsurface.passcolor4f_bufferoffset = 0;
8408 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8410 if ((wantnormals || wanttangents) && !normal3f)
8412 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8413 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8415 if (wanttangents && !svector3f)
8417 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8418 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8419 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8424 float RSurf_FogPoint(const float *v)
8426 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8427 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8428 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8429 float FogHeightFade = r_refdef.fogheightfade;
8431 unsigned int fogmasktableindex;
8432 if (r_refdef.fogplaneviewabove)
8433 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8435 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8436 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8437 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8440 float RSurf_FogVertex(const float *v)
8442 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8443 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8444 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8445 float FogHeightFade = rsurface.fogheightfade;
8447 unsigned int fogmasktableindex;
8448 if (r_refdef.fogplaneviewabove)
8449 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8451 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8452 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8453 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8456 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8459 for (i = 0;i < numelements;i++)
8460 outelement3i[i] = inelement3i[i] + adjust;
8463 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8464 extern cvar_t gl_vbo;
8465 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8473 int surfacefirsttriangle;
8474 int surfacenumtriangles;
8475 int surfacefirstvertex;
8476 int surfaceendvertex;
8477 int surfacenumvertices;
8478 int batchnumvertices;
8479 int batchnumtriangles;
8483 qboolean dynamicvertex;
8487 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8489 q3shaderinfo_deform_t *deform;
8490 const msurface_t *surface, *firstsurface;
8491 r_vertexmesh_t *vertexmesh;
8492 if (!texturenumsurfaces)
8494 // find vertex range of this surface batch
8496 firstsurface = texturesurfacelist[0];
8497 firsttriangle = firstsurface->num_firsttriangle;
8498 batchnumvertices = 0;
8499 batchnumtriangles = 0;
8500 firstvertex = endvertex = firstsurface->num_firstvertex;
8501 for (i = 0;i < texturenumsurfaces;i++)
8503 surface = texturesurfacelist[i];
8504 if (surface != firstsurface + i)
8506 surfacefirstvertex = surface->num_firstvertex;
8507 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8508 surfacenumvertices = surface->num_vertices;
8509 surfacenumtriangles = surface->num_triangles;
8510 if (firstvertex > surfacefirstvertex)
8511 firstvertex = surfacefirstvertex;
8512 if (endvertex < surfaceendvertex)
8513 endvertex = surfaceendvertex;
8514 batchnumvertices += surfacenumvertices;
8515 batchnumtriangles += surfacenumtriangles;
8518 // we now know the vertex range used, and if there are any gaps in it
8519 rsurface.batchfirstvertex = firstvertex;
8520 rsurface.batchnumvertices = endvertex - firstvertex;
8521 rsurface.batchfirsttriangle = firsttriangle;
8522 rsurface.batchnumtriangles = batchnumtriangles;
8524 // this variable holds flags for which properties have been updated that
8525 // may require regenerating vertexmesh array...
8528 // check if any dynamic vertex processing must occur
8529 dynamicvertex = false;
8531 // if there is a chance of animated vertex colors, it's a dynamic batch
8532 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8534 dynamicvertex = true;
8535 batchneed |= BATCHNEED_NOGAPS;
8536 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8539 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8541 switch (deform->deform)
8544 case Q3DEFORM_PROJECTIONSHADOW:
8545 case Q3DEFORM_TEXT0:
8546 case Q3DEFORM_TEXT1:
8547 case Q3DEFORM_TEXT2:
8548 case Q3DEFORM_TEXT3:
8549 case Q3DEFORM_TEXT4:
8550 case Q3DEFORM_TEXT5:
8551 case Q3DEFORM_TEXT6:
8552 case Q3DEFORM_TEXT7:
8555 case Q3DEFORM_AUTOSPRITE:
8556 dynamicvertex = true;
8557 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8558 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8560 case Q3DEFORM_AUTOSPRITE2:
8561 dynamicvertex = true;
8562 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8563 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8565 case Q3DEFORM_NORMAL:
8566 dynamicvertex = true;
8567 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8568 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8571 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8572 break; // if wavefunc is a nop, ignore this transform
8573 dynamicvertex = true;
8574 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8575 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8577 case Q3DEFORM_BULGE:
8578 dynamicvertex = true;
8579 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8580 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8583 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8584 break; // if wavefunc is a nop, ignore this transform
8585 dynamicvertex = true;
8586 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8587 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8591 switch(rsurface.texture->tcgen.tcgen)
8594 case Q3TCGEN_TEXTURE:
8596 case Q3TCGEN_LIGHTMAP:
8597 dynamicvertex = true;
8598 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8599 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8601 case Q3TCGEN_VECTOR:
8602 dynamicvertex = true;
8603 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8604 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8606 case Q3TCGEN_ENVIRONMENT:
8607 dynamicvertex = true;
8608 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8609 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8612 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8614 dynamicvertex = true;
8615 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8616 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8619 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8621 dynamicvertex = true;
8622 batchneed |= BATCHNEED_NOGAPS;
8623 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8626 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8628 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8629 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8630 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8631 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8632 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8633 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8634 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8637 // when the model data has no vertex buffer (dynamic mesh), we need to
8639 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8640 batchneed |= BATCHNEED_NOGAPS;
8642 // if needsupdate, we have to do a dynamic vertex batch for sure
8643 if (needsupdate & batchneed)
8644 dynamicvertex = true;
8646 // see if we need to build vertexmesh from arrays
8647 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8648 dynamicvertex = true;
8650 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8651 // also some drivers strongly dislike firstvertex
8652 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8653 dynamicvertex = true;
8655 rsurface.batchvertex3f = rsurface.modelvertex3f;
8656 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8657 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8658 rsurface.batchsvector3f = rsurface.modelsvector3f;
8659 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8660 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8661 rsurface.batchtvector3f = rsurface.modeltvector3f;
8662 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8663 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8664 rsurface.batchnormal3f = rsurface.modelnormal3f;
8665 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8666 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8667 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8668 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8669 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8670 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8671 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8672 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8673 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8674 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8675 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8676 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8677 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8678 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8679 rsurface.batchelement3i = rsurface.modelelement3i;
8680 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8681 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8682 rsurface.batchelement3s = rsurface.modelelement3s;
8683 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8684 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8686 // if any dynamic vertex processing has to occur in software, we copy the
8687 // entire surface list together before processing to rebase the vertices
8688 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8690 // if any gaps exist and we do not have a static vertex buffer, we have to
8691 // copy the surface list together to avoid wasting upload bandwidth on the
8692 // vertices in the gaps.
8694 // if gaps exist and we have a static vertex buffer, we still have to
8695 // combine the index buffer ranges into one dynamic index buffer.
8697 // in all cases we end up with data that can be drawn in one call.
8701 // static vertex data, just set pointers...
8702 rsurface.batchgeneratedvertex = false;
8703 // if there are gaps, we want to build a combined index buffer,
8704 // otherwise use the original static buffer with an appropriate offset
8707 // build a new triangle elements array for this batch
8708 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8709 rsurface.batchfirsttriangle = 0;
8711 for (i = 0;i < texturenumsurfaces;i++)
8713 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8714 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8715 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8716 numtriangles += surfacenumtriangles;
8718 rsurface.batchelement3i_indexbuffer = NULL;
8719 rsurface.batchelement3i_bufferoffset = 0;
8720 rsurface.batchelement3s = NULL;
8721 rsurface.batchelement3s_indexbuffer = NULL;
8722 rsurface.batchelement3s_bufferoffset = 0;
8723 if (endvertex <= 65536)
8725 // make a 16bit (unsigned short) index array if possible
8726 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8727 for (i = 0;i < numtriangles*3;i++)
8728 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8734 // something needs software processing, do it for real...
8735 // we only directly handle separate array data in this case and then
8736 // generate interleaved data if needed...
8737 rsurface.batchgeneratedvertex = true;
8739 // now copy the vertex data into a combined array and make an index array
8740 // (this is what Quake3 does all the time)
8741 //if (gaps || rsurface.batchfirstvertex)
8743 rsurface.batchvertex3fbuffer = NULL;
8744 rsurface.batchvertexmesh = NULL;
8745 rsurface.batchvertexmeshbuffer = NULL;
8746 rsurface.batchvertex3f = NULL;
8747 rsurface.batchvertex3f_vertexbuffer = NULL;
8748 rsurface.batchvertex3f_bufferoffset = 0;
8749 rsurface.batchsvector3f = NULL;
8750 rsurface.batchsvector3f_vertexbuffer = NULL;
8751 rsurface.batchsvector3f_bufferoffset = 0;
8752 rsurface.batchtvector3f = NULL;
8753 rsurface.batchtvector3f_vertexbuffer = NULL;
8754 rsurface.batchtvector3f_bufferoffset = 0;
8755 rsurface.batchnormal3f = NULL;
8756 rsurface.batchnormal3f_vertexbuffer = NULL;
8757 rsurface.batchnormal3f_bufferoffset = 0;
8758 rsurface.batchlightmapcolor4f = NULL;
8759 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8760 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8761 rsurface.batchtexcoordtexture2f = NULL;
8762 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8763 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8764 rsurface.batchtexcoordlightmap2f = NULL;
8765 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8766 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8767 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8768 rsurface.batchelement3i_indexbuffer = NULL;
8769 rsurface.batchelement3i_bufferoffset = 0;
8770 rsurface.batchelement3s = NULL;
8771 rsurface.batchelement3s_indexbuffer = NULL;
8772 rsurface.batchelement3s_bufferoffset = 0;
8773 // we'll only be setting up certain arrays as needed
8774 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8775 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8776 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8777 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8778 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8779 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8780 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8782 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8783 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8785 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8786 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8787 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8788 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8789 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8790 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8793 for (i = 0;i < texturenumsurfaces;i++)
8795 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8796 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8797 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8798 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8799 // copy only the data requested
8800 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8801 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8802 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8804 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8806 if (rsurface.batchvertex3f)
8807 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8809 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8811 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8813 if (rsurface.modelnormal3f)
8814 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8816 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8818 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8820 if (rsurface.modelsvector3f)
8822 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8823 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8827 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8828 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8831 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8833 if (rsurface.modellightmapcolor4f)
8834 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8836 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8838 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8840 if (rsurface.modeltexcoordtexture2f)
8841 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8843 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8845 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8847 if (rsurface.modeltexcoordlightmap2f)
8848 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8850 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8853 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8854 numvertices += surfacenumvertices;
8855 numtriangles += surfacenumtriangles;
8858 // generate a 16bit index array as well if possible
8859 // (in general, dynamic batches fit)
8860 if (numvertices <= 65536)
8862 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8863 for (i = 0;i < numtriangles*3;i++)
8864 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8867 // since we've copied everything, the batch now starts at 0
8868 rsurface.batchfirstvertex = 0;
8869 rsurface.batchnumvertices = batchnumvertices;
8870 rsurface.batchfirsttriangle = 0;
8871 rsurface.batchnumtriangles = batchnumtriangles;
8874 // q1bsp surfaces rendered in vertex color mode have to have colors
8875 // calculated based on lightstyles
8876 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8878 // generate color arrays for the surfaces in this list
8883 const unsigned char *lm;
8884 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8885 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8886 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8888 for (i = 0;i < texturenumsurfaces;i++)
8890 surface = texturesurfacelist[i];
8891 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8892 surfacenumvertices = surface->num_vertices;
8893 if (surface->lightmapinfo->samples)
8895 for (j = 0;j < surfacenumvertices;j++)
8897 lm = surface->lightmapinfo->samples + offsets[j];
8898 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8899 VectorScale(lm, scale, c);
8900 if (surface->lightmapinfo->styles[1] != 255)
8902 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8904 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8905 VectorMA(c, scale, lm, c);
8906 if (surface->lightmapinfo->styles[2] != 255)
8909 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8910 VectorMA(c, scale, lm, c);
8911 if (surface->lightmapinfo->styles[3] != 255)
8914 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8915 VectorMA(c, scale, lm, c);
8922 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);
8928 for (j = 0;j < surfacenumvertices;j++)
8930 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8937 // if vertices are deformed (sprite flares and things in maps, possibly
8938 // water waves, bulges and other deformations), modify the copied vertices
8940 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8942 switch (deform->deform)
8945 case Q3DEFORM_PROJECTIONSHADOW:
8946 case Q3DEFORM_TEXT0:
8947 case Q3DEFORM_TEXT1:
8948 case Q3DEFORM_TEXT2:
8949 case Q3DEFORM_TEXT3:
8950 case Q3DEFORM_TEXT4:
8951 case Q3DEFORM_TEXT5:
8952 case Q3DEFORM_TEXT6:
8953 case Q3DEFORM_TEXT7:
8956 case Q3DEFORM_AUTOSPRITE:
8957 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8958 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8959 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8960 VectorNormalize(newforward);
8961 VectorNormalize(newright);
8962 VectorNormalize(newup);
8963 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8964 // rsurface.batchvertex3f_vertexbuffer = NULL;
8965 // rsurface.batchvertex3f_bufferoffset = 0;
8966 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8967 // rsurface.batchsvector3f_vertexbuffer = NULL;
8968 // rsurface.batchsvector3f_bufferoffset = 0;
8969 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8970 // rsurface.batchtvector3f_vertexbuffer = NULL;
8971 // rsurface.batchtvector3f_bufferoffset = 0;
8972 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8973 // rsurface.batchnormal3f_vertexbuffer = NULL;
8974 // rsurface.batchnormal3f_bufferoffset = 0;
8975 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8976 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8977 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8978 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8979 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);
8980 // a single autosprite surface can contain multiple sprites...
8981 for (j = 0;j < batchnumvertices - 3;j += 4)
8983 VectorClear(center);
8984 for (i = 0;i < 4;i++)
8985 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8986 VectorScale(center, 0.25f, center);
8987 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8988 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8989 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8990 for (i = 0;i < 4;i++)
8992 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8993 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8996 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8997 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8998 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);
9000 case Q3DEFORM_AUTOSPRITE2:
9001 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9002 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9003 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9004 VectorNormalize(newforward);
9005 VectorNormalize(newright);
9006 VectorNormalize(newup);
9007 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9008 // rsurface.batchvertex3f_vertexbuffer = NULL;
9009 // rsurface.batchvertex3f_bufferoffset = 0;
9011 const float *v1, *v2;
9021 memset(shortest, 0, sizeof(shortest));
9022 // a single autosprite surface can contain multiple sprites...
9023 for (j = 0;j < batchnumvertices - 3;j += 4)
9025 VectorClear(center);
9026 for (i = 0;i < 4;i++)
9027 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9028 VectorScale(center, 0.25f, center);
9029 // find the two shortest edges, then use them to define the
9030 // axis vectors for rotating around the central axis
9031 for (i = 0;i < 6;i++)
9033 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9034 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9035 l = VectorDistance2(v1, v2);
9036 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9038 l += (1.0f / 1024.0f);
9039 if (shortest[0].length2 > l || i == 0)
9041 shortest[1] = shortest[0];
9042 shortest[0].length2 = l;
9043 shortest[0].v1 = v1;
9044 shortest[0].v2 = v2;
9046 else if (shortest[1].length2 > l || i == 1)
9048 shortest[1].length2 = l;
9049 shortest[1].v1 = v1;
9050 shortest[1].v2 = v2;
9053 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9054 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9055 // this calculates the right vector from the shortest edge
9056 // and the up vector from the edge midpoints
9057 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9058 VectorNormalize(right);
9059 VectorSubtract(end, start, up);
9060 VectorNormalize(up);
9061 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9062 VectorSubtract(rsurface.localvieworigin, center, forward);
9063 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9064 VectorNegate(forward, forward);
9065 VectorReflect(forward, 0, up, forward);
9066 VectorNormalize(forward);
9067 CrossProduct(up, forward, newright);
9068 VectorNormalize(newright);
9069 // rotate the quad around the up axis vector, this is made
9070 // especially easy by the fact we know the quad is flat,
9071 // so we only have to subtract the center position and
9072 // measure distance along the right vector, and then
9073 // multiply that by the newright vector and add back the
9075 // we also need to subtract the old position to undo the
9076 // displacement from the center, which we do with a
9077 // DotProduct, the subtraction/addition of center is also
9078 // optimized into DotProducts here
9079 l = DotProduct(right, center);
9080 for (i = 0;i < 4;i++)
9082 v1 = rsurface.batchvertex3f + 3*(j+i);
9083 f = DotProduct(right, v1) - l;
9084 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9088 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9090 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9091 // rsurface.batchnormal3f_vertexbuffer = NULL;
9092 // rsurface.batchnormal3f_bufferoffset = 0;
9093 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9095 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9097 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9098 // rsurface.batchsvector3f_vertexbuffer = NULL;
9099 // rsurface.batchsvector3f_bufferoffset = 0;
9100 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9101 // rsurface.batchtvector3f_vertexbuffer = NULL;
9102 // rsurface.batchtvector3f_bufferoffset = 0;
9103 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);
9106 case Q3DEFORM_NORMAL:
9107 // deform the normals to make reflections wavey
9108 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9109 rsurface.batchnormal3f_vertexbuffer = NULL;
9110 rsurface.batchnormal3f_bufferoffset = 0;
9111 for (j = 0;j < batchnumvertices;j++)
9114 float *normal = rsurface.batchnormal3f + 3*j;
9115 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9116 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9117 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9118 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9119 VectorNormalize(normal);
9121 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9123 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9124 // rsurface.batchsvector3f_vertexbuffer = NULL;
9125 // rsurface.batchsvector3f_bufferoffset = 0;
9126 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9127 // rsurface.batchtvector3f_vertexbuffer = NULL;
9128 // rsurface.batchtvector3f_bufferoffset = 0;
9129 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);
9133 // deform vertex array to make wavey water and flags and such
9134 waveparms[0] = deform->waveparms[0];
9135 waveparms[1] = deform->waveparms[1];
9136 waveparms[2] = deform->waveparms[2];
9137 waveparms[3] = deform->waveparms[3];
9138 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9139 break; // if wavefunc is a nop, don't make a dynamic vertex array
9140 // this is how a divisor of vertex influence on deformation
9141 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9142 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9143 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9144 // rsurface.batchvertex3f_vertexbuffer = NULL;
9145 // rsurface.batchvertex3f_bufferoffset = 0;
9146 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9147 // rsurface.batchnormal3f_vertexbuffer = NULL;
9148 // rsurface.batchnormal3f_bufferoffset = 0;
9149 for (j = 0;j < batchnumvertices;j++)
9151 // if the wavefunc depends on time, evaluate it per-vertex
9154 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9155 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9157 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9159 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9160 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9161 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9163 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9164 // rsurface.batchsvector3f_vertexbuffer = NULL;
9165 // rsurface.batchsvector3f_bufferoffset = 0;
9166 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9167 // rsurface.batchtvector3f_vertexbuffer = NULL;
9168 // rsurface.batchtvector3f_bufferoffset = 0;
9169 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);
9172 case Q3DEFORM_BULGE:
9173 // deform vertex array to make the surface have moving bulges
9174 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9175 // rsurface.batchvertex3f_vertexbuffer = NULL;
9176 // rsurface.batchvertex3f_bufferoffset = 0;
9177 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9178 // rsurface.batchnormal3f_vertexbuffer = NULL;
9179 // rsurface.batchnormal3f_bufferoffset = 0;
9180 for (j = 0;j < batchnumvertices;j++)
9182 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9183 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9185 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9186 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9187 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9189 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9190 // rsurface.batchsvector3f_vertexbuffer = NULL;
9191 // rsurface.batchsvector3f_bufferoffset = 0;
9192 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9193 // rsurface.batchtvector3f_vertexbuffer = NULL;
9194 // rsurface.batchtvector3f_bufferoffset = 0;
9195 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);
9199 // deform vertex array
9200 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9201 break; // if wavefunc is a nop, don't make a dynamic vertex array
9202 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9203 VectorScale(deform->parms, scale, waveparms);
9204 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9205 // rsurface.batchvertex3f_vertexbuffer = NULL;
9206 // rsurface.batchvertex3f_bufferoffset = 0;
9207 for (j = 0;j < batchnumvertices;j++)
9208 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9213 // generate texcoords based on the chosen texcoord source
9214 switch(rsurface.texture->tcgen.tcgen)
9217 case Q3TCGEN_TEXTURE:
9219 case Q3TCGEN_LIGHTMAP:
9220 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9221 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9222 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9223 if (rsurface.batchtexcoordlightmap2f)
9224 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9226 case Q3TCGEN_VECTOR:
9227 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9228 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9229 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9230 for (j = 0;j < batchnumvertices;j++)
9232 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9233 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9236 case Q3TCGEN_ENVIRONMENT:
9237 // make environment reflections using a spheremap
9238 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9239 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9240 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9241 for (j = 0;j < batchnumvertices;j++)
9243 // identical to Q3A's method, but executed in worldspace so
9244 // carried models can be shiny too
9246 float viewer[3], d, reflected[3], worldreflected[3];
9248 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9249 // VectorNormalize(viewer);
9251 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9253 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9254 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9255 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9256 // note: this is proportinal to viewer, so we can normalize later
9258 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9259 VectorNormalize(worldreflected);
9261 // note: this sphere map only uses world x and z!
9262 // so positive and negative y will LOOK THE SAME.
9263 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9264 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9268 // the only tcmod that needs software vertex processing is turbulent, so
9269 // check for it here and apply the changes if needed
9270 // and we only support that as the first one
9271 // (handling a mixture of turbulent and other tcmods would be problematic
9272 // without punting it entirely to a software path)
9273 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9275 amplitude = rsurface.texture->tcmods[0].parms[1];
9276 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9277 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9278 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9279 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9280 for (j = 0;j < batchnumvertices;j++)
9282 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);
9283 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9287 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9289 // convert the modified arrays to vertex structs
9290 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9291 // rsurface.batchvertexmeshbuffer = NULL;
9292 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9293 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9294 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9295 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9296 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9297 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9298 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9300 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9302 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9303 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9306 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9307 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9308 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9309 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9310 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9311 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9312 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9313 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9314 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9318 void RSurf_DrawBatch(void)
9320 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9321 // through the pipeline, killing it earlier in the pipeline would have
9322 // per-surface overhead rather than per-batch overhead, so it's best to
9323 // reject it here, before it hits glDraw.
9324 if (rsurface.batchnumtriangles == 0)
9327 // batch debugging code
9328 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9334 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9335 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9338 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9340 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9342 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9343 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);
9350 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);
9353 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9355 // pick the closest matching water plane
9356 int planeindex, vertexindex, bestplaneindex = -1;
9360 r_waterstate_waterplane_t *p;
9361 qboolean prepared = false;
9363 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9365 if(p->camera_entity != rsurface.texture->camera_entity)
9370 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9372 if(rsurface.batchnumvertices == 0)
9375 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9377 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9378 d += fabs(PlaneDiff(vert, &p->plane));
9380 if (bestd > d || bestplaneindex < 0)
9383 bestplaneindex = planeindex;
9386 return bestplaneindex;
9387 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9388 // this situation though, as it might be better to render single larger
9389 // batches with useless stuff (backface culled for example) than to
9390 // render multiple smaller batches
9393 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9396 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9397 rsurface.passcolor4f_vertexbuffer = 0;
9398 rsurface.passcolor4f_bufferoffset = 0;
9399 for (i = 0;i < rsurface.batchnumvertices;i++)
9400 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9403 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9410 if (rsurface.passcolor4f)
9412 // generate color arrays
9413 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9414 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9415 rsurface.passcolor4f_vertexbuffer = 0;
9416 rsurface.passcolor4f_bufferoffset = 0;
9417 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)
9419 f = RSurf_FogVertex(v);
9428 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9429 rsurface.passcolor4f_vertexbuffer = 0;
9430 rsurface.passcolor4f_bufferoffset = 0;
9431 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9433 f = RSurf_FogVertex(v);
9442 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9449 if (!rsurface.passcolor4f)
9451 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9452 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9453 rsurface.passcolor4f_vertexbuffer = 0;
9454 rsurface.passcolor4f_bufferoffset = 0;
9455 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)
9457 f = RSurf_FogVertex(v);
9458 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9459 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9460 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9465 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9470 if (!rsurface.passcolor4f)
9472 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9473 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9474 rsurface.passcolor4f_vertexbuffer = 0;
9475 rsurface.passcolor4f_bufferoffset = 0;
9476 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9485 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9490 if (!rsurface.passcolor4f)
9492 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9493 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9494 rsurface.passcolor4f_vertexbuffer = 0;
9495 rsurface.passcolor4f_bufferoffset = 0;
9496 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9498 c2[0] = c[0] + r_refdef.scene.ambient;
9499 c2[1] = c[1] + r_refdef.scene.ambient;
9500 c2[2] = c[2] + r_refdef.scene.ambient;
9505 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9508 rsurface.passcolor4f = NULL;
9509 rsurface.passcolor4f_vertexbuffer = 0;
9510 rsurface.passcolor4f_bufferoffset = 0;
9511 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9512 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9513 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9514 GL_Color(r, g, b, a);
9515 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9519 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9521 // TODO: optimize applyfog && applycolor case
9522 // just apply fog if necessary, and tint the fog color array if necessary
9523 rsurface.passcolor4f = NULL;
9524 rsurface.passcolor4f_vertexbuffer = 0;
9525 rsurface.passcolor4f_bufferoffset = 0;
9526 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9527 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9528 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9529 GL_Color(r, g, b, a);
9533 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9536 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9537 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9538 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
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_ClampColor(void)
9551 if (!rsurface.passcolor4f)
9553 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9555 c2[0] = bound(0.0f, c1[0], 1.0f);
9556 c2[1] = bound(0.0f, c1[1], 1.0f);
9557 c2[2] = bound(0.0f, c1[2], 1.0f);
9558 c2[3] = bound(0.0f, c1[3], 1.0f);
9562 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9572 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9573 rsurface.passcolor4f_vertexbuffer = 0;
9574 rsurface.passcolor4f_bufferoffset = 0;
9575 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)
9577 f = -DotProduct(r_refdef.view.forward, n);
9579 f = f * 0.85 + 0.15; // work around so stuff won't get black
9580 f *= r_refdef.lightmapintensity;
9581 Vector4Set(c, f, f, f, 1);
9585 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9587 RSurf_DrawBatch_GL11_ApplyFakeLight();
9588 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9589 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9590 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9591 GL_Color(r, g, b, a);
9595 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9603 vec3_t ambientcolor;
9604 vec3_t diffusecolor;
9608 VectorCopy(rsurface.modellight_lightdir, lightdir);
9609 f = 0.5f * r_refdef.lightmapintensity;
9610 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9611 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9612 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9613 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9614 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9615 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9617 if (VectorLength2(diffusecolor) > 0)
9619 // q3-style directional shading
9620 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9621 rsurface.passcolor4f_vertexbuffer = 0;
9622 rsurface.passcolor4f_bufferoffset = 0;
9623 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)
9625 if ((f = DotProduct(n, lightdir)) > 0)
9626 VectorMA(ambientcolor, f, diffusecolor, c);
9628 VectorCopy(ambientcolor, c);
9635 *applycolor = false;
9639 *r = ambientcolor[0];
9640 *g = ambientcolor[1];
9641 *b = ambientcolor[2];
9642 rsurface.passcolor4f = NULL;
9643 rsurface.passcolor4f_vertexbuffer = 0;
9644 rsurface.passcolor4f_bufferoffset = 0;
9648 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9650 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9651 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9652 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9653 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9654 GL_Color(r, g, b, a);
9658 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9666 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9667 rsurface.passcolor4f_vertexbuffer = 0;
9668 rsurface.passcolor4f_bufferoffset = 0;
9670 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9672 f = 1 - RSurf_FogVertex(v);
9680 void RSurf_SetupDepthAndCulling(void)
9682 // submodels are biased to avoid z-fighting with world surfaces that they
9683 // may be exactly overlapping (avoids z-fighting artifacts on certain
9684 // doors and things in Quake maps)
9685 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9686 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9687 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9688 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9691 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9693 // transparent sky would be ridiculous
9694 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9696 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9697 skyrenderlater = true;
9698 RSurf_SetupDepthAndCulling();
9700 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9701 // skymasking on them, and Quake3 never did sky masking (unlike
9702 // software Quake and software Quake2), so disable the sky masking
9703 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9704 // and skymasking also looks very bad when noclipping outside the
9705 // level, so don't use it then either.
9706 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9708 R_Mesh_ResetTextureState();
9709 if (skyrendermasked)
9711 R_SetupShader_DepthOrShadow(false);
9712 // depth-only (masking)
9713 GL_ColorMask(0,0,0,0);
9714 // just to make sure that braindead drivers don't draw
9715 // anything despite that colormask...
9716 GL_BlendFunc(GL_ZERO, GL_ONE);
9717 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9718 if (rsurface.batchvertex3fbuffer)
9719 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9721 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9725 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9727 GL_BlendFunc(GL_ONE, GL_ZERO);
9728 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9729 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9730 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9733 if (skyrendermasked)
9734 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9736 R_Mesh_ResetTextureState();
9737 GL_Color(1, 1, 1, 1);
9740 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9741 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9742 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9744 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9748 // render screenspace normalmap to texture
9750 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9754 // bind lightmap texture
9756 // water/refraction/reflection/camera surfaces have to be handled specially
9757 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9759 int start, end, startplaneindex;
9760 for (start = 0;start < texturenumsurfaces;start = end)
9762 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9763 if(startplaneindex < 0)
9765 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9766 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9770 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9772 // now that we have a batch using the same planeindex, render it
9773 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9775 // render water or distortion background
9777 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);
9779 // blend surface on top
9780 GL_DepthMask(false);
9781 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9784 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9786 // render surface with reflection texture as input
9787 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9788 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);
9795 // render surface batch normally
9796 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9797 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);
9801 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9803 // OpenGL 1.3 path - anything not completely ancient
9804 qboolean applycolor;
9807 const texturelayer_t *layer;
9808 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);
9809 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9811 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9814 int layertexrgbscale;
9815 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9817 if (layerindex == 0)
9821 GL_AlphaTest(false);
9822 GL_DepthFunc(GL_EQUAL);
9825 GL_DepthMask(layer->depthmask && writedepth);
9826 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9827 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9829 layertexrgbscale = 4;
9830 VectorScale(layer->color, 0.25f, layercolor);
9832 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9834 layertexrgbscale = 2;
9835 VectorScale(layer->color, 0.5f, layercolor);
9839 layertexrgbscale = 1;
9840 VectorScale(layer->color, 1.0f, layercolor);
9842 layercolor[3] = layer->color[3];
9843 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9844 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9845 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9846 switch (layer->type)
9848 case TEXTURELAYERTYPE_LITTEXTURE:
9849 // single-pass lightmapped texture with 2x rgbscale
9850 R_Mesh_TexBind(0, r_texture_white);
9851 R_Mesh_TexMatrix(0, NULL);
9852 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9853 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9854 R_Mesh_TexBind(1, layer->texture);
9855 R_Mesh_TexMatrix(1, &layer->texmatrix);
9856 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9857 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9858 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9859 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9860 else if (FAKELIGHT_ENABLED)
9861 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9862 else if (rsurface.uselightmaptexture)
9863 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9865 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9867 case TEXTURELAYERTYPE_TEXTURE:
9868 // singletexture unlit texture with transparency support
9869 R_Mesh_TexBind(0, layer->texture);
9870 R_Mesh_TexMatrix(0, &layer->texmatrix);
9871 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9872 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9873 R_Mesh_TexBind(1, 0);
9874 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9875 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9877 case TEXTURELAYERTYPE_FOG:
9878 // singletexture fogging
9881 R_Mesh_TexBind(0, layer->texture);
9882 R_Mesh_TexMatrix(0, &layer->texmatrix);
9883 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9884 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9888 R_Mesh_TexBind(0, 0);
9889 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9891 R_Mesh_TexBind(1, 0);
9892 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9893 // generate a color array for the fog pass
9894 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9895 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9899 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9902 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9904 GL_DepthFunc(GL_LEQUAL);
9905 GL_AlphaTest(false);
9909 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9911 // OpenGL 1.1 - crusty old voodoo path
9914 const texturelayer_t *layer;
9915 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);
9916 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9918 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9920 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9922 if (layerindex == 0)
9926 GL_AlphaTest(false);
9927 GL_DepthFunc(GL_EQUAL);
9930 GL_DepthMask(layer->depthmask && writedepth);
9931 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9932 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9933 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9934 switch (layer->type)
9936 case TEXTURELAYERTYPE_LITTEXTURE:
9937 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9939 // two-pass lit texture with 2x rgbscale
9940 // first the lightmap pass
9941 R_Mesh_TexBind(0, r_texture_white);
9942 R_Mesh_TexMatrix(0, NULL);
9943 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9944 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9945 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9946 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9947 else if (FAKELIGHT_ENABLED)
9948 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9949 else if (rsurface.uselightmaptexture)
9950 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9952 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9953 // then apply the texture to it
9954 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9955 R_Mesh_TexBind(0, layer->texture);
9956 R_Mesh_TexMatrix(0, &layer->texmatrix);
9957 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9958 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9959 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);
9963 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9964 R_Mesh_TexBind(0, layer->texture);
9965 R_Mesh_TexMatrix(0, &layer->texmatrix);
9966 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9967 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9968 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9969 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);
9971 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);
9974 case TEXTURELAYERTYPE_TEXTURE:
9975 // singletexture unlit texture with transparency support
9976 R_Mesh_TexBind(0, layer->texture);
9977 R_Mesh_TexMatrix(0, &layer->texmatrix);
9978 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9979 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9980 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);
9982 case TEXTURELAYERTYPE_FOG:
9983 // singletexture fogging
9986 R_Mesh_TexBind(0, layer->texture);
9987 R_Mesh_TexMatrix(0, &layer->texmatrix);
9988 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9989 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9993 R_Mesh_TexBind(0, 0);
9994 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9996 // generate a color array for the fog pass
9997 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9998 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10002 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10005 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10007 GL_DepthFunc(GL_LEQUAL);
10008 GL_AlphaTest(false);
10012 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10016 r_vertexgeneric_t *batchvertex;
10019 // R_Mesh_ResetTextureState();
10020 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10022 if(rsurface.texture && rsurface.texture->currentskinframe)
10024 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10025 c[3] *= rsurface.texture->currentalpha;
10035 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10037 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10038 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10039 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10042 // brighten it up (as texture value 127 means "unlit")
10043 c[0] *= 2 * r_refdef.view.colorscale;
10044 c[1] *= 2 * r_refdef.view.colorscale;
10045 c[2] *= 2 * r_refdef.view.colorscale;
10047 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10048 c[3] *= r_wateralpha.value;
10050 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10052 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10053 GL_DepthMask(false);
10055 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10057 GL_BlendFunc(GL_ONE, GL_ONE);
10058 GL_DepthMask(false);
10060 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10062 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10063 GL_DepthMask(false);
10065 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10067 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10068 GL_DepthMask(false);
10072 GL_BlendFunc(GL_ONE, GL_ZERO);
10073 GL_DepthMask(writedepth);
10076 if (r_showsurfaces.integer == 3)
10078 rsurface.passcolor4f = NULL;
10080 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10082 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10084 rsurface.passcolor4f = NULL;
10085 rsurface.passcolor4f_vertexbuffer = 0;
10086 rsurface.passcolor4f_bufferoffset = 0;
10088 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10090 qboolean applycolor = true;
10093 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10095 r_refdef.lightmapintensity = 1;
10096 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10097 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10099 else if (FAKELIGHT_ENABLED)
10101 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10103 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10104 RSurf_DrawBatch_GL11_ApplyFakeLight();
10105 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10109 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10111 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10112 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10113 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10116 if(!rsurface.passcolor4f)
10117 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10119 RSurf_DrawBatch_GL11_ApplyAmbient();
10120 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10121 if(r_refdef.fogenabled)
10122 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10123 RSurf_DrawBatch_GL11_ClampColor();
10125 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10126 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10129 else if (!r_refdef.view.showdebug)
10131 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10132 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10133 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10135 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10136 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10138 R_Mesh_PrepareVertices_Generic_Unlock();
10141 else if (r_showsurfaces.integer == 4)
10143 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10144 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10145 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10147 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10148 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10149 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10151 R_Mesh_PrepareVertices_Generic_Unlock();
10154 else if (r_showsurfaces.integer == 2)
10157 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10158 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10159 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10161 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10162 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10163 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10164 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10165 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10166 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10167 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10169 R_Mesh_PrepareVertices_Generic_Unlock();
10170 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10174 int texturesurfaceindex;
10176 const msurface_t *surface;
10177 float surfacecolor4f[4];
10178 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10179 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10181 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10183 surface = texturesurfacelist[texturesurfaceindex];
10184 k = (int)(((size_t)surface) / sizeof(msurface_t));
10185 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10186 for (j = 0;j < surface->num_vertices;j++)
10188 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10189 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10193 R_Mesh_PrepareVertices_Generic_Unlock();
10198 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10201 RSurf_SetupDepthAndCulling();
10202 if (r_showsurfaces.integer)
10204 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10207 switch (vid.renderpath)
10209 case RENDERPATH_GL20:
10210 case RENDERPATH_D3D9:
10211 case RENDERPATH_D3D10:
10212 case RENDERPATH_D3D11:
10213 case RENDERPATH_SOFT:
10214 case RENDERPATH_GLES2:
10215 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10217 case RENDERPATH_GL13:
10218 case RENDERPATH_GLES1:
10219 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10221 case RENDERPATH_GL11:
10222 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10228 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10231 RSurf_SetupDepthAndCulling();
10232 if (r_showsurfaces.integer)
10234 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10237 switch (vid.renderpath)
10239 case RENDERPATH_GL20:
10240 case RENDERPATH_D3D9:
10241 case RENDERPATH_D3D10:
10242 case RENDERPATH_D3D11:
10243 case RENDERPATH_SOFT:
10244 case RENDERPATH_GLES2:
10245 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10247 case RENDERPATH_GL13:
10248 case RENDERPATH_GLES1:
10249 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10251 case RENDERPATH_GL11:
10252 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10258 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10261 int texturenumsurfaces, endsurface;
10262 texture_t *texture;
10263 const msurface_t *surface;
10264 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10266 // if the model is static it doesn't matter what value we give for
10267 // wantnormals and wanttangents, so this logic uses only rules applicable
10268 // to a model, knowing that they are meaningless otherwise
10269 if (ent == r_refdef.scene.worldentity)
10270 RSurf_ActiveWorldEntity();
10271 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10272 RSurf_ActiveModelEntity(ent, false, false, false);
10275 switch (vid.renderpath)
10277 case RENDERPATH_GL20:
10278 case RENDERPATH_D3D9:
10279 case RENDERPATH_D3D10:
10280 case RENDERPATH_D3D11:
10281 case RENDERPATH_SOFT:
10282 case RENDERPATH_GLES2:
10283 RSurf_ActiveModelEntity(ent, true, true, false);
10285 case RENDERPATH_GL11:
10286 case RENDERPATH_GL13:
10287 case RENDERPATH_GLES1:
10288 RSurf_ActiveModelEntity(ent, true, false, false);
10293 if (r_transparentdepthmasking.integer)
10295 qboolean setup = false;
10296 for (i = 0;i < numsurfaces;i = j)
10299 surface = rsurface.modelsurfaces + surfacelist[i];
10300 texture = surface->texture;
10301 rsurface.texture = R_GetCurrentTexture(texture);
10302 rsurface.lightmaptexture = NULL;
10303 rsurface.deluxemaptexture = NULL;
10304 rsurface.uselightmaptexture = false;
10305 // scan ahead until we find a different texture
10306 endsurface = min(i + 1024, numsurfaces);
10307 texturenumsurfaces = 0;
10308 texturesurfacelist[texturenumsurfaces++] = surface;
10309 for (;j < endsurface;j++)
10311 surface = rsurface.modelsurfaces + surfacelist[j];
10312 if (texture != surface->texture)
10314 texturesurfacelist[texturenumsurfaces++] = surface;
10316 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10318 // render the range of surfaces as depth
10322 GL_ColorMask(0,0,0,0);
10324 GL_DepthTest(true);
10325 GL_BlendFunc(GL_ONE, GL_ZERO);
10326 GL_DepthMask(true);
10327 // R_Mesh_ResetTextureState();
10328 R_SetupShader_DepthOrShadow(false);
10330 RSurf_SetupDepthAndCulling();
10331 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10332 if (rsurface.batchvertex3fbuffer)
10333 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10335 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10339 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10342 for (i = 0;i < numsurfaces;i = j)
10345 surface = rsurface.modelsurfaces + surfacelist[i];
10346 texture = surface->texture;
10347 rsurface.texture = R_GetCurrentTexture(texture);
10348 // scan ahead until we find a different texture
10349 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10350 texturenumsurfaces = 0;
10351 texturesurfacelist[texturenumsurfaces++] = surface;
10352 if(FAKELIGHT_ENABLED)
10354 rsurface.lightmaptexture = NULL;
10355 rsurface.deluxemaptexture = NULL;
10356 rsurface.uselightmaptexture = false;
10357 for (;j < endsurface;j++)
10359 surface = rsurface.modelsurfaces + surfacelist[j];
10360 if (texture != surface->texture)
10362 texturesurfacelist[texturenumsurfaces++] = surface;
10367 rsurface.lightmaptexture = surface->lightmaptexture;
10368 rsurface.deluxemaptexture = surface->deluxemaptexture;
10369 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10370 for (;j < endsurface;j++)
10372 surface = rsurface.modelsurfaces + surfacelist[j];
10373 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10375 texturesurfacelist[texturenumsurfaces++] = surface;
10378 // render the range of surfaces
10379 if (ent == r_refdef.scene.worldentity)
10380 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10382 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10384 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10387 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10389 // transparent surfaces get pushed off into the transparent queue
10390 int surfacelistindex;
10391 const msurface_t *surface;
10392 vec3_t tempcenter, center;
10393 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10395 surface = texturesurfacelist[surfacelistindex];
10396 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10397 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10398 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10399 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10400 if (queueentity->transparent_offset) // transparent offset
10402 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10403 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10404 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10406 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10410 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10412 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10414 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10416 RSurf_SetupDepthAndCulling();
10417 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10418 if (rsurface.batchvertex3fbuffer)
10419 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10421 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10425 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10427 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10430 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10433 if (!rsurface.texture->currentnumlayers)
10435 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10436 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10438 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10440 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10441 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10442 else if (!rsurface.texture->currentnumlayers)
10444 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10446 // in the deferred case, transparent surfaces were queued during prepass
10447 if (!r_shadow_usingdeferredprepass)
10448 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10452 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10453 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10458 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10461 texture_t *texture;
10462 R_FrameData_SetMark();
10463 // break the surface list down into batches by texture and use of lightmapping
10464 for (i = 0;i < numsurfaces;i = j)
10467 // texture is the base texture pointer, rsurface.texture is the
10468 // current frame/skin the texture is directing us to use (for example
10469 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10470 // use skin 1 instead)
10471 texture = surfacelist[i]->texture;
10472 rsurface.texture = R_GetCurrentTexture(texture);
10473 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10475 // if this texture is not the kind we want, skip ahead to the next one
10476 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10480 if(FAKELIGHT_ENABLED || depthonly || prepass)
10482 rsurface.lightmaptexture = NULL;
10483 rsurface.deluxemaptexture = NULL;
10484 rsurface.uselightmaptexture = false;
10485 // simply scan ahead until we find a different texture or lightmap state
10486 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10491 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10492 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10493 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10494 // simply scan ahead until we find a different texture or lightmap state
10495 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10498 // render the range of surfaces
10499 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10501 R_FrameData_ReturnToMark();
10504 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10508 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10511 if (!rsurface.texture->currentnumlayers)
10513 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10514 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10516 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10518 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10519 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10520 else if (!rsurface.texture->currentnumlayers)
10522 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10524 // in the deferred case, transparent surfaces were queued during prepass
10525 if (!r_shadow_usingdeferredprepass)
10526 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10530 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10531 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10536 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10539 texture_t *texture;
10540 R_FrameData_SetMark();
10541 // break the surface list down into batches by texture and use of lightmapping
10542 for (i = 0;i < numsurfaces;i = j)
10545 // texture is the base texture pointer, rsurface.texture is the
10546 // current frame/skin the texture is directing us to use (for example
10547 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10548 // use skin 1 instead)
10549 texture = surfacelist[i]->texture;
10550 rsurface.texture = R_GetCurrentTexture(texture);
10551 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10553 // if this texture is not the kind we want, skip ahead to the next one
10554 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10558 if(FAKELIGHT_ENABLED || depthonly || prepass)
10560 rsurface.lightmaptexture = NULL;
10561 rsurface.deluxemaptexture = NULL;
10562 rsurface.uselightmaptexture = false;
10563 // simply scan ahead until we find a different texture or lightmap state
10564 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10569 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10570 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10571 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10572 // simply scan ahead until we find a different texture or lightmap state
10573 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10576 // render the range of surfaces
10577 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10579 R_FrameData_ReturnToMark();
10582 float locboxvertex3f[6*4*3] =
10584 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10585 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10586 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10587 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10588 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10589 1,0,0, 0,0,0, 0,1,0, 1,1,0
10592 unsigned short locboxelements[6*2*3] =
10597 12,13,14, 12,14,15,
10598 16,17,18, 16,18,19,
10602 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10605 cl_locnode_t *loc = (cl_locnode_t *)ent;
10607 float vertex3f[6*4*3];
10609 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10610 GL_DepthMask(false);
10611 GL_DepthRange(0, 1);
10612 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10613 GL_DepthTest(true);
10614 GL_CullFace(GL_NONE);
10615 R_EntityMatrix(&identitymatrix);
10617 // R_Mesh_ResetTextureState();
10619 i = surfacelist[0];
10620 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10621 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10622 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10623 surfacelist[0] < 0 ? 0.5f : 0.125f);
10625 if (VectorCompare(loc->mins, loc->maxs))
10627 VectorSet(size, 2, 2, 2);
10628 VectorMA(loc->mins, -0.5f, size, mins);
10632 VectorCopy(loc->mins, mins);
10633 VectorSubtract(loc->maxs, loc->mins, size);
10636 for (i = 0;i < 6*4*3;)
10637 for (j = 0;j < 3;j++, i++)
10638 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10640 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10641 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10642 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10645 void R_DrawLocs(void)
10648 cl_locnode_t *loc, *nearestloc;
10650 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10651 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10653 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10654 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10658 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10660 if (decalsystem->decals)
10661 Mem_Free(decalsystem->decals);
10662 memset(decalsystem, 0, sizeof(*decalsystem));
10665 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)
10668 tridecal_t *decals;
10671 // expand or initialize the system
10672 if (decalsystem->maxdecals <= decalsystem->numdecals)
10674 decalsystem_t old = *decalsystem;
10675 qboolean useshortelements;
10676 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10677 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10678 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)));
10679 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10680 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10681 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10682 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10683 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10684 if (decalsystem->numdecals)
10685 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10687 Mem_Free(old.decals);
10688 for (i = 0;i < decalsystem->maxdecals*3;i++)
10689 decalsystem->element3i[i] = i;
10690 if (useshortelements)
10691 for (i = 0;i < decalsystem->maxdecals*3;i++)
10692 decalsystem->element3s[i] = i;
10695 // grab a decal and search for another free slot for the next one
10696 decals = decalsystem->decals;
10697 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10698 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10700 decalsystem->freedecal = i;
10701 if (decalsystem->numdecals <= i)
10702 decalsystem->numdecals = i + 1;
10704 // initialize the decal
10706 decal->triangleindex = triangleindex;
10707 decal->surfaceindex = surfaceindex;
10708 decal->decalsequence = decalsequence;
10709 decal->color4f[0][0] = c0[0];
10710 decal->color4f[0][1] = c0[1];
10711 decal->color4f[0][2] = c0[2];
10712 decal->color4f[0][3] = 1;
10713 decal->color4f[1][0] = c1[0];
10714 decal->color4f[1][1] = c1[1];
10715 decal->color4f[1][2] = c1[2];
10716 decal->color4f[1][3] = 1;
10717 decal->color4f[2][0] = c2[0];
10718 decal->color4f[2][1] = c2[1];
10719 decal->color4f[2][2] = c2[2];
10720 decal->color4f[2][3] = 1;
10721 decal->vertex3f[0][0] = v0[0];
10722 decal->vertex3f[0][1] = v0[1];
10723 decal->vertex3f[0][2] = v0[2];
10724 decal->vertex3f[1][0] = v1[0];
10725 decal->vertex3f[1][1] = v1[1];
10726 decal->vertex3f[1][2] = v1[2];
10727 decal->vertex3f[2][0] = v2[0];
10728 decal->vertex3f[2][1] = v2[1];
10729 decal->vertex3f[2][2] = v2[2];
10730 decal->texcoord2f[0][0] = t0[0];
10731 decal->texcoord2f[0][1] = t0[1];
10732 decal->texcoord2f[1][0] = t1[0];
10733 decal->texcoord2f[1][1] = t1[1];
10734 decal->texcoord2f[2][0] = t2[0];
10735 decal->texcoord2f[2][1] = t2[1];
10736 TriangleNormal(v0, v1, v2, decal->plane);
10737 VectorNormalize(decal->plane);
10738 decal->plane[3] = DotProduct(v0, decal->plane);
10741 extern cvar_t cl_decals_bias;
10742 extern cvar_t cl_decals_models;
10743 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10744 // baseparms, parms, temps
10745 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)
10750 const float *vertex3f;
10751 const float *normal3f;
10753 float points[2][9][3];
10760 e = rsurface.modelelement3i + 3*triangleindex;
10762 vertex3f = rsurface.modelvertex3f;
10763 normal3f = rsurface.modelnormal3f;
10767 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10769 index = 3*e[cornerindex];
10770 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10775 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10777 index = 3*e[cornerindex];
10778 VectorCopy(vertex3f + index, v[cornerindex]);
10783 //TriangleNormal(v[0], v[1], v[2], normal);
10784 //if (DotProduct(normal, localnormal) < 0.0f)
10786 // clip by each of the box planes formed from the projection matrix
10787 // if anything survives, we emit the decal
10788 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]);
10791 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]);
10794 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]);
10797 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]);
10800 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]);
10803 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]);
10806 // some part of the triangle survived, so we have to accept it...
10809 // dynamic always uses the original triangle
10811 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10813 index = 3*e[cornerindex];
10814 VectorCopy(vertex3f + index, v[cornerindex]);
10817 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10819 // convert vertex positions to texcoords
10820 Matrix4x4_Transform(projection, v[cornerindex], temp);
10821 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10822 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10823 // calculate distance fade from the projection origin
10824 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10825 f = bound(0.0f, f, 1.0f);
10826 c[cornerindex][0] = r * f;
10827 c[cornerindex][1] = g * f;
10828 c[cornerindex][2] = b * f;
10829 c[cornerindex][3] = 1.0f;
10830 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10833 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);
10835 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10836 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);
10838 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)
10840 matrix4x4_t projection;
10841 decalsystem_t *decalsystem;
10844 const msurface_t *surface;
10845 const msurface_t *surfaces;
10846 const int *surfacelist;
10847 const texture_t *texture;
10849 int numsurfacelist;
10850 int surfacelistindex;
10853 float localorigin[3];
10854 float localnormal[3];
10855 float localmins[3];
10856 float localmaxs[3];
10859 float planes[6][4];
10862 int bih_triangles_count;
10863 int bih_triangles[256];
10864 int bih_surfaces[256];
10866 decalsystem = &ent->decalsystem;
10867 model = ent->model;
10868 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10870 R_DecalSystem_Reset(&ent->decalsystem);
10874 if (!model->brush.data_leafs && !cl_decals_models.integer)
10876 if (decalsystem->model)
10877 R_DecalSystem_Reset(decalsystem);
10881 if (decalsystem->model != model)
10882 R_DecalSystem_Reset(decalsystem);
10883 decalsystem->model = model;
10885 RSurf_ActiveModelEntity(ent, true, false, false);
10887 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10888 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10889 VectorNormalize(localnormal);
10890 localsize = worldsize*rsurface.inversematrixscale;
10891 localmins[0] = localorigin[0] - localsize;
10892 localmins[1] = localorigin[1] - localsize;
10893 localmins[2] = localorigin[2] - localsize;
10894 localmaxs[0] = localorigin[0] + localsize;
10895 localmaxs[1] = localorigin[1] + localsize;
10896 localmaxs[2] = localorigin[2] + localsize;
10898 //VectorCopy(localnormal, planes[4]);
10899 //VectorVectors(planes[4], planes[2], planes[0]);
10900 AnglesFromVectors(angles, localnormal, NULL, false);
10901 AngleVectors(angles, planes[0], planes[2], planes[4]);
10902 VectorNegate(planes[0], planes[1]);
10903 VectorNegate(planes[2], planes[3]);
10904 VectorNegate(planes[4], planes[5]);
10905 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10906 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10907 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10908 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10909 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10910 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10915 matrix4x4_t forwardprojection;
10916 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10917 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10922 float projectionvector[4][3];
10923 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10924 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10925 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10926 projectionvector[0][0] = planes[0][0] * ilocalsize;
10927 projectionvector[0][1] = planes[1][0] * ilocalsize;
10928 projectionvector[0][2] = planes[2][0] * ilocalsize;
10929 projectionvector[1][0] = planes[0][1] * ilocalsize;
10930 projectionvector[1][1] = planes[1][1] * ilocalsize;
10931 projectionvector[1][2] = planes[2][1] * ilocalsize;
10932 projectionvector[2][0] = planes[0][2] * ilocalsize;
10933 projectionvector[2][1] = planes[1][2] * ilocalsize;
10934 projectionvector[2][2] = planes[2][2] * ilocalsize;
10935 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10936 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10937 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10938 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10942 dynamic = model->surfmesh.isanimated;
10943 numsurfacelist = model->nummodelsurfaces;
10944 surfacelist = model->sortedmodelsurfaces;
10945 surfaces = model->data_surfaces;
10948 bih_triangles_count = -1;
10951 if(model->render_bih.numleafs)
10952 bih = &model->render_bih;
10953 else if(model->collision_bih.numleafs)
10954 bih = &model->collision_bih;
10957 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10958 if(bih_triangles_count == 0)
10960 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10962 if(bih_triangles_count > 0)
10964 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10966 surfaceindex = bih_surfaces[triangleindex];
10967 surface = surfaces + surfaceindex;
10968 texture = surface->texture;
10969 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10971 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10973 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10978 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10980 surfaceindex = surfacelist[surfacelistindex];
10981 surface = surfaces + surfaceindex;
10982 // check cull box first because it rejects more than any other check
10983 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10985 // skip transparent surfaces
10986 texture = surface->texture;
10987 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10989 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10991 numtriangles = surface->num_triangles;
10992 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10993 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10998 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10999 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)
11001 int renderentityindex;
11002 float worldmins[3];
11003 float worldmaxs[3];
11004 entity_render_t *ent;
11006 if (!cl_decals_newsystem.integer)
11009 worldmins[0] = worldorigin[0] - worldsize;
11010 worldmins[1] = worldorigin[1] - worldsize;
11011 worldmins[2] = worldorigin[2] - worldsize;
11012 worldmaxs[0] = worldorigin[0] + worldsize;
11013 worldmaxs[1] = worldorigin[1] + worldsize;
11014 worldmaxs[2] = worldorigin[2] + worldsize;
11016 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11018 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11020 ent = r_refdef.scene.entities[renderentityindex];
11021 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11024 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11028 typedef struct r_decalsystem_splatqueue_s
11030 vec3_t worldorigin;
11031 vec3_t worldnormal;
11037 r_decalsystem_splatqueue_t;
11039 int r_decalsystem_numqueued = 0;
11040 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11042 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)
11044 r_decalsystem_splatqueue_t *queue;
11046 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11049 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11050 VectorCopy(worldorigin, queue->worldorigin);
11051 VectorCopy(worldnormal, queue->worldnormal);
11052 Vector4Set(queue->color, r, g, b, a);
11053 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11054 queue->worldsize = worldsize;
11055 queue->decalsequence = cl.decalsequence++;
11058 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11061 r_decalsystem_splatqueue_t *queue;
11063 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11064 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);
11065 r_decalsystem_numqueued = 0;
11068 extern cvar_t cl_decals_max;
11069 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11072 decalsystem_t *decalsystem = &ent->decalsystem;
11079 if (!decalsystem->numdecals)
11082 if (r_showsurfaces.integer)
11085 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11087 R_DecalSystem_Reset(decalsystem);
11091 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11092 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11094 if (decalsystem->lastupdatetime)
11095 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11098 decalsystem->lastupdatetime = r_refdef.scene.time;
11099 decal = decalsystem->decals;
11100 numdecals = decalsystem->numdecals;
11102 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11104 if (decal->color4f[0][3])
11106 decal->lived += frametime;
11107 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11109 memset(decal, 0, sizeof(*decal));
11110 if (decalsystem->freedecal > i)
11111 decalsystem->freedecal = i;
11115 decal = decalsystem->decals;
11116 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11119 // collapse the array by shuffling the tail decals into the gaps
11122 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11123 decalsystem->freedecal++;
11124 if (decalsystem->freedecal == numdecals)
11126 decal[decalsystem->freedecal] = decal[--numdecals];
11129 decalsystem->numdecals = numdecals;
11131 if (numdecals <= 0)
11133 // if there are no decals left, reset decalsystem
11134 R_DecalSystem_Reset(decalsystem);
11138 extern skinframe_t *decalskinframe;
11139 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11142 decalsystem_t *decalsystem = &ent->decalsystem;
11151 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11154 numdecals = decalsystem->numdecals;
11158 if (r_showsurfaces.integer)
11161 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11163 R_DecalSystem_Reset(decalsystem);
11167 // if the model is static it doesn't matter what value we give for
11168 // wantnormals and wanttangents, so this logic uses only rules applicable
11169 // to a model, knowing that they are meaningless otherwise
11170 if (ent == r_refdef.scene.worldentity)
11171 RSurf_ActiveWorldEntity();
11173 RSurf_ActiveModelEntity(ent, false, false, false);
11175 decalsystem->lastupdatetime = r_refdef.scene.time;
11176 decal = decalsystem->decals;
11178 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11180 // update vertex positions for animated models
11181 v3f = decalsystem->vertex3f;
11182 c4f = decalsystem->color4f;
11183 t2f = decalsystem->texcoord2f;
11184 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11186 if (!decal->color4f[0][3])
11189 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11193 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11196 // update color values for fading decals
11197 if (decal->lived >= cl_decals_time.value)
11198 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11202 c4f[ 0] = decal->color4f[0][0] * alpha;
11203 c4f[ 1] = decal->color4f[0][1] * alpha;
11204 c4f[ 2] = decal->color4f[0][2] * alpha;
11206 c4f[ 4] = decal->color4f[1][0] * alpha;
11207 c4f[ 5] = decal->color4f[1][1] * alpha;
11208 c4f[ 6] = decal->color4f[1][2] * alpha;
11210 c4f[ 8] = decal->color4f[2][0] * alpha;
11211 c4f[ 9] = decal->color4f[2][1] * alpha;
11212 c4f[10] = decal->color4f[2][2] * alpha;
11215 t2f[0] = decal->texcoord2f[0][0];
11216 t2f[1] = decal->texcoord2f[0][1];
11217 t2f[2] = decal->texcoord2f[1][0];
11218 t2f[3] = decal->texcoord2f[1][1];
11219 t2f[4] = decal->texcoord2f[2][0];
11220 t2f[5] = decal->texcoord2f[2][1];
11222 // update vertex positions for animated models
11223 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11225 e = rsurface.modelelement3i + 3*decal->triangleindex;
11226 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11227 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11228 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11232 VectorCopy(decal->vertex3f[0], v3f);
11233 VectorCopy(decal->vertex3f[1], v3f + 3);
11234 VectorCopy(decal->vertex3f[2], v3f + 6);
11237 if (r_refdef.fogenabled)
11239 alpha = RSurf_FogVertex(v3f);
11240 VectorScale(c4f, alpha, c4f);
11241 alpha = RSurf_FogVertex(v3f + 3);
11242 VectorScale(c4f + 4, alpha, c4f + 4);
11243 alpha = RSurf_FogVertex(v3f + 6);
11244 VectorScale(c4f + 8, alpha, c4f + 8);
11255 r_refdef.stats.drawndecals += numtris;
11257 // now render the decals all at once
11258 // (this assumes they all use one particle font texture!)
11259 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);
11260 // R_Mesh_ResetTextureState();
11261 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11262 GL_DepthMask(false);
11263 GL_DepthRange(0, 1);
11264 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11265 GL_DepthTest(true);
11266 GL_CullFace(GL_NONE);
11267 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11268 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11269 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11273 static void R_DrawModelDecals(void)
11277 // fade faster when there are too many decals
11278 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11279 for (i = 0;i < r_refdef.scene.numentities;i++)
11280 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11282 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11283 for (i = 0;i < r_refdef.scene.numentities;i++)
11284 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11285 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11287 R_DecalSystem_ApplySplatEntitiesQueue();
11289 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11290 for (i = 0;i < r_refdef.scene.numentities;i++)
11291 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11293 r_refdef.stats.totaldecals += numdecals;
11295 if (r_showsurfaces.integer)
11298 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11300 for (i = 0;i < r_refdef.scene.numentities;i++)
11302 if (!r_refdef.viewcache.entityvisible[i])
11304 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11305 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11309 extern cvar_t mod_collision_bih;
11310 void R_DrawDebugModel(void)
11312 entity_render_t *ent = rsurface.entity;
11313 int i, j, k, l, flagsmask;
11314 const msurface_t *surface;
11315 dp_model_t *model = ent->model;
11318 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11321 if (r_showoverdraw.value > 0)
11323 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11324 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11325 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11326 GL_DepthTest(false);
11327 GL_DepthMask(false);
11328 GL_DepthRange(0, 1);
11329 GL_BlendFunc(GL_ONE, GL_ONE);
11330 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11332 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11334 rsurface.texture = R_GetCurrentTexture(surface->texture);
11335 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11337 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11338 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11339 if (!rsurface.texture->currentlayers->depthmask)
11340 GL_Color(c, 0, 0, 1.0f);
11341 else if (ent == r_refdef.scene.worldentity)
11342 GL_Color(c, c, c, 1.0f);
11344 GL_Color(0, c, 0, 1.0f);
11345 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11349 rsurface.texture = NULL;
11352 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11354 // R_Mesh_ResetTextureState();
11355 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11356 GL_DepthRange(0, 1);
11357 GL_DepthTest(!r_showdisabledepthtest.integer);
11358 GL_DepthMask(false);
11359 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11361 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11365 qboolean cullbox = ent == r_refdef.scene.worldentity;
11366 const q3mbrush_t *brush;
11367 const bih_t *bih = &model->collision_bih;
11368 const bih_leaf_t *bihleaf;
11369 float vertex3f[3][3];
11370 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11372 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11374 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11376 switch (bihleaf->type)
11379 brush = model->brush.data_brushes + bihleaf->itemindex;
11380 if (brush->colbrushf && brush->colbrushf->numtriangles)
11382 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);
11383 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11384 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11387 case BIH_COLLISIONTRIANGLE:
11388 triangleindex = bihleaf->itemindex;
11389 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11390 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11391 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11392 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);
11393 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11394 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11396 case BIH_RENDERTRIANGLE:
11397 triangleindex = bihleaf->itemindex;
11398 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11399 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11400 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11401 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);
11402 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11403 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11409 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11412 if (r_showtris.integer && qglPolygonMode)
11414 if (r_showdisabledepthtest.integer)
11416 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11417 GL_DepthMask(false);
11421 GL_BlendFunc(GL_ONE, GL_ZERO);
11422 GL_DepthMask(true);
11424 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11425 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11427 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11429 rsurface.texture = R_GetCurrentTexture(surface->texture);
11430 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11432 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11433 if (!rsurface.texture->currentlayers->depthmask)
11434 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11435 else if (ent == r_refdef.scene.worldentity)
11436 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11438 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11439 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11443 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11444 rsurface.texture = NULL;
11447 if (r_shownormals.value != 0 && qglBegin)
11449 if (r_showdisabledepthtest.integer)
11451 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11452 GL_DepthMask(false);
11456 GL_BlendFunc(GL_ONE, GL_ZERO);
11457 GL_DepthMask(true);
11459 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11461 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11463 rsurface.texture = R_GetCurrentTexture(surface->texture);
11464 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11466 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11467 qglBegin(GL_LINES);
11468 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11470 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11472 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11473 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11474 qglVertex3f(v[0], v[1], v[2]);
11475 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11476 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11477 qglVertex3f(v[0], v[1], v[2]);
11480 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11482 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11484 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11485 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11486 qglVertex3f(v[0], v[1], v[2]);
11487 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11488 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11489 qglVertex3f(v[0], v[1], v[2]);
11492 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11494 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11496 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11497 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11498 qglVertex3f(v[0], v[1], v[2]);
11499 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11500 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11501 qglVertex3f(v[0], v[1], v[2]);
11504 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11506 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11508 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11509 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11510 qglVertex3f(v[0], v[1], v[2]);
11511 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11512 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11513 qglVertex3f(v[0], v[1], v[2]);
11520 rsurface.texture = NULL;
11525 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11526 int r_maxsurfacelist = 0;
11527 const msurface_t **r_surfacelist = NULL;
11528 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11530 int i, j, endj, flagsmask;
11531 dp_model_t *model = r_refdef.scene.worldmodel;
11532 msurface_t *surfaces;
11533 unsigned char *update;
11534 int numsurfacelist = 0;
11538 if (r_maxsurfacelist < model->num_surfaces)
11540 r_maxsurfacelist = model->num_surfaces;
11542 Mem_Free((msurface_t**)r_surfacelist);
11543 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11546 RSurf_ActiveWorldEntity();
11548 surfaces = model->data_surfaces;
11549 update = model->brushq1.lightmapupdateflags;
11551 // update light styles on this submodel
11552 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11554 model_brush_lightstyleinfo_t *style;
11555 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11557 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11559 int *list = style->surfacelist;
11560 style->value = r_refdef.scene.lightstylevalue[style->style];
11561 for (j = 0;j < style->numsurfaces;j++)
11562 update[list[j]] = true;
11567 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11571 R_DrawDebugModel();
11572 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11576 rsurface.lightmaptexture = NULL;
11577 rsurface.deluxemaptexture = NULL;
11578 rsurface.uselightmaptexture = false;
11579 rsurface.texture = NULL;
11580 rsurface.rtlight = NULL;
11581 numsurfacelist = 0;
11582 // add visible surfaces to draw list
11583 for (i = 0;i < model->nummodelsurfaces;i++)
11585 j = model->sortedmodelsurfaces[i];
11586 if (r_refdef.viewcache.world_surfacevisible[j])
11587 r_surfacelist[numsurfacelist++] = surfaces + j;
11589 // update lightmaps if needed
11590 if (model->brushq1.firstrender)
11592 model->brushq1.firstrender = false;
11593 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11595 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11599 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11600 if (r_refdef.viewcache.world_surfacevisible[j])
11602 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11604 // don't do anything if there were no surfaces
11605 if (!numsurfacelist)
11607 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11610 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11612 // add to stats if desired
11613 if (r_speeds.integer && !skysurfaces && !depthonly)
11615 r_refdef.stats.world_surfaces += numsurfacelist;
11616 for (j = 0;j < numsurfacelist;j++)
11617 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11620 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11623 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11625 int i, j, endj, flagsmask;
11626 dp_model_t *model = ent->model;
11627 msurface_t *surfaces;
11628 unsigned char *update;
11629 int numsurfacelist = 0;
11633 if (r_maxsurfacelist < model->num_surfaces)
11635 r_maxsurfacelist = model->num_surfaces;
11637 Mem_Free((msurface_t **)r_surfacelist);
11638 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11641 // if the model is static it doesn't matter what value we give for
11642 // wantnormals and wanttangents, so this logic uses only rules applicable
11643 // to a model, knowing that they are meaningless otherwise
11644 if (ent == r_refdef.scene.worldentity)
11645 RSurf_ActiveWorldEntity();
11646 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11647 RSurf_ActiveModelEntity(ent, false, false, false);
11649 RSurf_ActiveModelEntity(ent, true, true, true);
11650 else if (depthonly)
11652 switch (vid.renderpath)
11654 case RENDERPATH_GL20:
11655 case RENDERPATH_D3D9:
11656 case RENDERPATH_D3D10:
11657 case RENDERPATH_D3D11:
11658 case RENDERPATH_SOFT:
11659 case RENDERPATH_GLES2:
11660 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11662 case RENDERPATH_GL11:
11663 case RENDERPATH_GL13:
11664 case RENDERPATH_GLES1:
11665 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11671 switch (vid.renderpath)
11673 case RENDERPATH_GL20:
11674 case RENDERPATH_D3D9:
11675 case RENDERPATH_D3D10:
11676 case RENDERPATH_D3D11:
11677 case RENDERPATH_SOFT:
11678 case RENDERPATH_GLES2:
11679 RSurf_ActiveModelEntity(ent, true, true, false);
11681 case RENDERPATH_GL11:
11682 case RENDERPATH_GL13:
11683 case RENDERPATH_GLES1:
11684 RSurf_ActiveModelEntity(ent, true, false, false);
11689 surfaces = model->data_surfaces;
11690 update = model->brushq1.lightmapupdateflags;
11692 // update light styles
11693 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11695 model_brush_lightstyleinfo_t *style;
11696 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11698 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11700 int *list = style->surfacelist;
11701 style->value = r_refdef.scene.lightstylevalue[style->style];
11702 for (j = 0;j < style->numsurfaces;j++)
11703 update[list[j]] = true;
11708 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11712 R_DrawDebugModel();
11713 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11717 rsurface.lightmaptexture = NULL;
11718 rsurface.deluxemaptexture = NULL;
11719 rsurface.uselightmaptexture = false;
11720 rsurface.texture = NULL;
11721 rsurface.rtlight = NULL;
11722 numsurfacelist = 0;
11723 // add visible surfaces to draw list
11724 for (i = 0;i < model->nummodelsurfaces;i++)
11725 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11726 // don't do anything if there were no surfaces
11727 if (!numsurfacelist)
11729 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11732 // update lightmaps if needed
11736 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11741 R_BuildLightMap(ent, surfaces + j);
11746 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11748 R_BuildLightMap(ent, surfaces + j);
11749 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11751 // add to stats if desired
11752 if (r_speeds.integer && !skysurfaces && !depthonly)
11754 r_refdef.stats.entities_surfaces += numsurfacelist;
11755 for (j = 0;j < numsurfacelist;j++)
11756 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11759 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11762 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11764 static texture_t texture;
11765 static msurface_t surface;
11766 const msurface_t *surfacelist = &surface;
11768 // fake enough texture and surface state to render this geometry
11770 texture.update_lastrenderframe = -1; // regenerate this texture
11771 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11772 texture.currentskinframe = skinframe;
11773 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11774 texture.offsetmapping = OFFSETMAPPING_OFF;
11775 texture.offsetscale = 1;
11776 texture.specularscalemod = 1;
11777 texture.specularpowermod = 1;
11779 surface.texture = &texture;
11780 surface.num_triangles = numtriangles;
11781 surface.num_firsttriangle = firsttriangle;
11782 surface.num_vertices = numvertices;
11783 surface.num_firstvertex = firstvertex;
11786 rsurface.texture = R_GetCurrentTexture(surface.texture);
11787 rsurface.lightmaptexture = NULL;
11788 rsurface.deluxemaptexture = NULL;
11789 rsurface.uselightmaptexture = false;
11790 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11793 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)
11795 static msurface_t surface;
11796 const msurface_t *surfacelist = &surface;
11798 // fake enough texture and surface state to render this geometry
11799 surface.texture = texture;
11800 surface.num_triangles = numtriangles;
11801 surface.num_firsttriangle = firsttriangle;
11802 surface.num_vertices = numvertices;
11803 surface.num_firstvertex = firstvertex;
11806 rsurface.texture = R_GetCurrentTexture(surface.texture);
11807 rsurface.lightmaptexture = NULL;
11808 rsurface.deluxemaptexture = NULL;
11809 rsurface.uselightmaptexture = false;
11810 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);