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.88", "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", "1", "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", "10", "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", "100", "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_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
103 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
106 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
107 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
110 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
111 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
112 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."};
113 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
114 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
115 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
116 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."};
117 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
118 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
119 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
120 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
121 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"};
122 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"};
123 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
124 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
126 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
127 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
128 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"};
129 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
130 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
132 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
133 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
134 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
135 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
136 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
137 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
138 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
139 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
141 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)"};
142 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"};
144 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
145 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
146 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
148 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"};
149 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"};
150 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
151 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
152 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"};
153 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)"};
154 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)"};
155 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
157 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)"};
158 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
159 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)"};
160 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
161 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)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
164 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
174 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)"};
175 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
176 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"};
177 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
178 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
179 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
180 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"};
182 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
183 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
184 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
185 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
187 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
188 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
189 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
190 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
191 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
192 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
193 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
195 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
196 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
197 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
198 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)"};
199 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
200 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
201 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
202 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
204 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
205 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
207 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"};
209 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"};
211 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
213 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
215 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
216 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"};
218 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."};
220 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)"};
222 extern cvar_t v_glslgamma;
224 extern qboolean v_flipped_state;
226 static struct r_bloomstate_s
231 int bloomwidth, bloomheight;
233 textype_t texturetype;
234 int viewfbo; // used to check if r_viewfbo cvar has changed
236 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
237 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
238 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
240 int screentexturewidth, screentextureheight;
241 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
243 int bloomtexturewidth, bloomtextureheight;
244 rtexture_t *texture_bloom;
246 // arrays for rendering the screen passes
247 float screentexcoord2f[8];
248 float bloomtexcoord2f[8];
249 float offsettexcoord2f[8];
251 r_viewport_t viewport;
255 r_waterstate_t r_waterstate;
257 /// shadow volume bsp struct with automatically growing nodes buffer
260 rtexture_t *r_texture_blanknormalmap;
261 rtexture_t *r_texture_white;
262 rtexture_t *r_texture_grey128;
263 rtexture_t *r_texture_black;
264 rtexture_t *r_texture_notexture;
265 rtexture_t *r_texture_whitecube;
266 rtexture_t *r_texture_normalizationcube;
267 rtexture_t *r_texture_fogattenuation;
268 rtexture_t *r_texture_fogheighttexture;
269 rtexture_t *r_texture_gammaramps;
270 unsigned int r_texture_gammaramps_serial;
271 //rtexture_t *r_texture_fogintensity;
272 rtexture_t *r_texture_reflectcube;
274 // TODO: hash lookups?
275 typedef struct cubemapinfo_s
282 int r_texture_numcubemaps;
283 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
285 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
286 unsigned int r_numqueries;
287 unsigned int r_maxqueries;
289 typedef struct r_qwskincache_s
291 char name[MAX_QPATH];
292 skinframe_t *skinframe;
296 static r_qwskincache_t *r_qwskincache;
297 static int r_qwskincache_size;
299 /// vertex coordinates for a quad that covers the screen exactly
300 extern const float r_screenvertex3f[12];
301 extern const float r_d3dscreenvertex3f[12];
302 const float r_screenvertex3f[12] =
309 const float r_d3dscreenvertex3f[12] =
317 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
320 for (i = 0;i < verts;i++)
331 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
334 for (i = 0;i < verts;i++)
344 // FIXME: move this to client?
347 if (gamemode == GAME_NEHAHRA)
349 Cvar_Set("gl_fogenable", "0");
350 Cvar_Set("gl_fogdensity", "0.2");
351 Cvar_Set("gl_fogred", "0.3");
352 Cvar_Set("gl_foggreen", "0.3");
353 Cvar_Set("gl_fogblue", "0.3");
355 r_refdef.fog_density = 0;
356 r_refdef.fog_red = 0;
357 r_refdef.fog_green = 0;
358 r_refdef.fog_blue = 0;
359 r_refdef.fog_alpha = 1;
360 r_refdef.fog_start = 0;
361 r_refdef.fog_end = 16384;
362 r_refdef.fog_height = 1<<30;
363 r_refdef.fog_fadedepth = 128;
364 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
367 static void R_BuildBlankTextures(void)
369 unsigned char data[4];
370 data[2] = 128; // normal X
371 data[1] = 128; // normal Y
372 data[0] = 255; // normal Z
373 data[3] = 128; // height
374 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 static void R_BuildNoTexture(void)
395 unsigned char pix[16][16][4];
396 // this makes a light grey/dark grey checkerboard texture
397 for (y = 0;y < 16;y++)
399 for (x = 0;x < 16;x++)
401 if ((y < 8) ^ (x < 8))
417 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
420 static void R_BuildWhiteCube(void)
422 unsigned char data[6*1*1*4];
423 memset(data, 255, sizeof(data));
424 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
427 static void R_BuildNormalizationCube(void)
431 vec_t s, t, intensity;
434 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
435 for (side = 0;side < 6;side++)
437 for (y = 0;y < NORMSIZE;y++)
439 for (x = 0;x < NORMSIZE;x++)
441 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
442 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
477 intensity = 127.0f / sqrt(DotProduct(v, v));
478 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
479 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
480 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
481 data[((side*64+y)*64+x)*4+3] = 255;
485 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
489 static void R_BuildFogTexture(void)
493 unsigned char data1[FOGWIDTH][4];
494 //unsigned char data2[FOGWIDTH][4];
497 r_refdef.fogmasktable_start = r_refdef.fog_start;
498 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
499 r_refdef.fogmasktable_range = r_refdef.fogrange;
500 r_refdef.fogmasktable_density = r_refdef.fog_density;
502 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
503 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505 d = (x * r - r_refdef.fogmasktable_start);
506 if(developer_extra.integer)
507 Con_DPrintf("%f ", d);
509 if (r_fog_exp2.integer)
510 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
513 if(developer_extra.integer)
514 Con_DPrintf(" : %f ", alpha);
515 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
516 if(developer_extra.integer)
517 Con_DPrintf(" = %f\n", alpha);
518 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
521 for (x = 0;x < FOGWIDTH;x++)
523 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
528 //data2[x][0] = 255 - b;
529 //data2[x][1] = 255 - b;
530 //data2[x][2] = 255 - b;
533 if (r_texture_fogattenuation)
535 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
536 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
540 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
541 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
545 static void R_BuildFogHeightTexture(void)
547 unsigned char *inpixels;
555 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
556 if (r_refdef.fogheighttexturename[0])
557 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
560 r_refdef.fog_height_tablesize = 0;
561 if (r_texture_fogheighttexture)
562 R_FreeTexture(r_texture_fogheighttexture);
563 r_texture_fogheighttexture = NULL;
564 if (r_refdef.fog_height_table2d)
565 Mem_Free(r_refdef.fog_height_table2d);
566 r_refdef.fog_height_table2d = NULL;
567 if (r_refdef.fog_height_table1d)
568 Mem_Free(r_refdef.fog_height_table1d);
569 r_refdef.fog_height_table1d = NULL;
573 r_refdef.fog_height_tablesize = size;
574 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
575 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
576 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578 // LordHavoc: now the magic - what is that table2d for? it is a cooked
579 // average fog color table accounting for every fog layer between a point
580 // and the camera. (Note: attenuation is handled separately!)
581 for (y = 0;y < size;y++)
583 for (x = 0;x < size;x++)
589 for (j = x;j <= y;j++)
591 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
597 for (j = x;j >= y;j--)
599 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
604 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
605 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
606 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
607 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
610 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
613 //=======================================================================================================================================================
615 static const char *builtinshaderstring =
616 #include "shader_glsl.h"
619 const char *builtinhlslshaderstring =
620 #include "shader_hlsl.h"
623 char *glslshaderstring = NULL;
624 char *hlslshaderstring = NULL;
626 //=======================================================================================================================================================
628 typedef struct shaderpermutationinfo_s
633 shaderpermutationinfo_t;
635 typedef struct shadermodeinfo_s
637 const char *vertexfilename;
638 const char *geometryfilename;
639 const char *fragmentfilename;
645 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
646 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
648 {"#define USEDIFFUSE\n", " diffuse"},
649 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
650 {"#define USEVIEWTINT\n", " viewtint"},
651 {"#define USECOLORMAPPING\n", " colormapping"},
652 {"#define USESATURATION\n", " saturation"},
653 {"#define USEFOGINSIDE\n", " foginside"},
654 {"#define USEFOGOUTSIDE\n", " fogoutside"},
655 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
656 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
657 {"#define USEGAMMARAMPS\n", " gammaramps"},
658 {"#define USECUBEFILTER\n", " cubefilter"},
659 {"#define USEGLOW\n", " glow"},
660 {"#define USEBLOOM\n", " bloom"},
661 {"#define USESPECULAR\n", " specular"},
662 {"#define USEPOSTPROCESSING\n", " postprocessing"},
663 {"#define USEREFLECTION\n", " reflection"},
664 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
665 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
666 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
667 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
668 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
669 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
670 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
671 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673 {"#define USEALPHAKILL\n", " alphakill"},
674 {"#define USEREFLECTCUBE\n", " reflectcube"},
675 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676 {"#define USEBOUNCEGRID\n", " bouncegrid"},
677 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
678 {"#define USETRIPPY\n", " trippy"},
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
726 struct r_glsl_permutation_s *hashnext;
728 unsigned int permutation;
730 /// indicates if we have tried compiling this permutation already
732 /// 0 if compilation failed
734 // texture units assigned to each detected uniform
735 int tex_Texture_First;
736 int tex_Texture_Second;
737 int tex_Texture_GammaRamps;
738 int tex_Texture_Normal;
739 int tex_Texture_Color;
740 int tex_Texture_Gloss;
741 int tex_Texture_Glow;
742 int tex_Texture_SecondaryNormal;
743 int tex_Texture_SecondaryColor;
744 int tex_Texture_SecondaryGloss;
745 int tex_Texture_SecondaryGlow;
746 int tex_Texture_Pants;
747 int tex_Texture_Shirt;
748 int tex_Texture_FogHeightTexture;
749 int tex_Texture_FogMask;
750 int tex_Texture_Lightmap;
751 int tex_Texture_Deluxemap;
752 int tex_Texture_Attenuation;
753 int tex_Texture_Cube;
754 int tex_Texture_Refraction;
755 int tex_Texture_Reflection;
756 int tex_Texture_ShadowMap2D;
757 int tex_Texture_CubeProjection;
758 int tex_Texture_ScreenDepth;
759 int tex_Texture_ScreenNormalMap;
760 int tex_Texture_ScreenDiffuse;
761 int tex_Texture_ScreenSpecular;
762 int tex_Texture_ReflectMask;
763 int tex_Texture_ReflectCube;
764 int tex_Texture_BounceGrid;
765 /// locations of detected uniforms in program object, or -1 if not found
766 int loc_Texture_First;
767 int loc_Texture_Second;
768 int loc_Texture_GammaRamps;
769 int loc_Texture_Normal;
770 int loc_Texture_Color;
771 int loc_Texture_Gloss;
772 int loc_Texture_Glow;
773 int loc_Texture_SecondaryNormal;
774 int loc_Texture_SecondaryColor;
775 int loc_Texture_SecondaryGloss;
776 int loc_Texture_SecondaryGlow;
777 int loc_Texture_Pants;
778 int loc_Texture_Shirt;
779 int loc_Texture_FogHeightTexture;
780 int loc_Texture_FogMask;
781 int loc_Texture_Lightmap;
782 int loc_Texture_Deluxemap;
783 int loc_Texture_Attenuation;
784 int loc_Texture_Cube;
785 int loc_Texture_Refraction;
786 int loc_Texture_Reflection;
787 int loc_Texture_ShadowMap2D;
788 int loc_Texture_CubeProjection;
789 int loc_Texture_ScreenDepth;
790 int loc_Texture_ScreenNormalMap;
791 int loc_Texture_ScreenDiffuse;
792 int loc_Texture_ScreenSpecular;
793 int loc_Texture_ReflectMask;
794 int loc_Texture_ReflectCube;
795 int loc_Texture_BounceGrid;
797 int loc_BloomBlur_Parameters;
799 int loc_Color_Ambient;
800 int loc_Color_Diffuse;
801 int loc_Color_Specular;
805 int loc_DeferredColor_Ambient;
806 int loc_DeferredColor_Diffuse;
807 int loc_DeferredColor_Specular;
808 int loc_DeferredMod_Diffuse;
809 int loc_DeferredMod_Specular;
810 int loc_DistortScaleRefractReflect;
813 int loc_FogHeightFade;
815 int loc_FogPlaneViewDist;
816 int loc_FogRangeRecip;
819 int loc_LightPosition;
820 int loc_OffsetMapping_ScaleSteps;
822 int loc_ReflectColor;
823 int loc_ReflectFactor;
824 int loc_ReflectOffset;
825 int loc_RefractColor;
827 int loc_ScreenCenterRefractReflect;
828 int loc_ScreenScaleRefractReflect;
829 int loc_ScreenToDepth;
830 int loc_ShadowMap_Parameters;
831 int loc_ShadowMap_TextureScale;
832 int loc_SpecularPower;
837 int loc_ViewTintColor;
839 int loc_ModelToLight;
841 int loc_BackgroundTexMatrix;
842 int loc_ModelViewProjectionMatrix;
843 int loc_ModelViewMatrix;
844 int loc_PixelToScreenTexCoord;
845 int loc_ModelToReflectCube;
846 int loc_ShadowMapMatrix;
847 int loc_BloomColorSubtract;
848 int loc_NormalmapScrollBlend;
849 int loc_BounceGridMatrix;
850 int loc_BounceGridIntensity;
852 r_glsl_permutation_t;
854 #define SHADERPERMUTATION_HASHSIZE 256
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
861 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
867 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
869 #define SHADERSTATICPARMS_COUNT 7
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
878 static int r_compileshader_staticparms_save[1];
879 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
883 if (r_glsl_saturation_redcompensate.integer)
884 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885 if (r_glsl_vertextextureblend_usebothalphas.integer)
886 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887 if (r_shadow_glossexact.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889 if (r_glsl_postprocess.integer)
891 if (r_glsl_postprocess_uservec1_enable.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893 if (r_glsl_postprocess_uservec2_enable.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895 if (r_glsl_postprocess_uservec3_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897 if (r_glsl_postprocess_uservec4_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
900 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 shaderstaticparms_count = 0;
913 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
931 //unsigned int hashdepth = 0;
932 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933 r_glsl_permutation_t *p;
934 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
936 if (p->mode == mode && p->permutation == permutation)
938 //if (hashdepth > 10)
939 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
944 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
946 p->permutation = permutation;
947 p->hashnext = r_glsl_permutationhash[mode][hashindex];
948 r_glsl_permutationhash[mode][hashindex] = p;
949 //if (hashdepth > 10)
950 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
957 if (!filename || !filename[0])
959 if (!strcmp(filename, "glsl/default.glsl"))
961 if (!glslshaderstring)
963 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964 if (glslshaderstring)
965 Con_DPrintf("Loading shaders from file %s...\n", filename);
967 glslshaderstring = (char *)builtinshaderstring;
969 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
973 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
976 if (printfromdisknotice)
977 Con_DPrintf("from disk %s... ", filename);
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
987 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988 char *vertexstring, *geometrystring, *fragmentstring;
989 char permutationname[256];
990 int vertstrings_count = 0;
991 int geomstrings_count = 0;
992 int fragstrings_count = 0;
993 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002 permutationname[0] = 0;
1003 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1007 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1009 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010 if(vid.support.gl20shaders130)
1012 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1020 // the first pretext is which type of shader to compile as
1021 // (later these will all be bound together as a program object)
1022 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1026 // the second pretext is the mode (for example a light source)
1027 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1032 // now add all the permutation pretexts
1033 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1035 if (permutation & (1<<i))
1037 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1044 // keep line numbers correct
1045 vertstrings_list[vertstrings_count++] = "\n";
1046 geomstrings_list[geomstrings_count++] = "\n";
1047 fragstrings_list[fragstrings_count++] = "\n";
1052 R_CompileShader_AddStaticParms(mode, permutation);
1053 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054 vertstrings_count += shaderstaticparms_count;
1055 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056 geomstrings_count += shaderstaticparms_count;
1057 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058 fragstrings_count += shaderstaticparms_count;
1060 // now append the shader text itself
1061 vertstrings_list[vertstrings_count++] = vertexstring;
1062 geomstrings_list[geomstrings_count++] = geometrystring;
1063 fragstrings_list[fragstrings_count++] = fragmentstring;
1065 // if any sources were NULL, clear the respective list
1067 vertstrings_count = 0;
1068 if (!geometrystring)
1069 geomstrings_count = 0;
1070 if (!fragmentstring)
1071 fragstrings_count = 0;
1073 // compile the shader program
1074 if (vertstrings_count + geomstrings_count + fragstrings_count)
1075 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1079 qglUseProgram(p->program);CHECKGLERROR
1080 // look up all the uniform variable names we care about, so we don't
1081 // have to look them up every time we set them
1083 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1084 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1085 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1087 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1088 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1089 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1090 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1095 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1096 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1098 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1102 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1103 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1104 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1114 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1116 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1117 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1118 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1119 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1120 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1121 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1122 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1129 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1130 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1131 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1132 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1134 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1135 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1136 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1137 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1139 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1140 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1141 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1142 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1143 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1144 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1147 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1150 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1151 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1152 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1153 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1154 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1155 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1156 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1157 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1158 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168 // initialize the samplers to refer to the texture units we use
1169 p->tex_Texture_First = -1;
1170 p->tex_Texture_Second = -1;
1171 p->tex_Texture_GammaRamps = -1;
1172 p->tex_Texture_Normal = -1;
1173 p->tex_Texture_Color = -1;
1174 p->tex_Texture_Gloss = -1;
1175 p->tex_Texture_Glow = -1;
1176 p->tex_Texture_SecondaryNormal = -1;
1177 p->tex_Texture_SecondaryColor = -1;
1178 p->tex_Texture_SecondaryGloss = -1;
1179 p->tex_Texture_SecondaryGlow = -1;
1180 p->tex_Texture_Pants = -1;
1181 p->tex_Texture_Shirt = -1;
1182 p->tex_Texture_FogHeightTexture = -1;
1183 p->tex_Texture_FogMask = -1;
1184 p->tex_Texture_Lightmap = -1;
1185 p->tex_Texture_Deluxemap = -1;
1186 p->tex_Texture_Attenuation = -1;
1187 p->tex_Texture_Cube = -1;
1188 p->tex_Texture_Refraction = -1;
1189 p->tex_Texture_Reflection = -1;
1190 p->tex_Texture_ShadowMap2D = -1;
1191 p->tex_Texture_CubeProjection = -1;
1192 p->tex_Texture_ScreenDepth = -1;
1193 p->tex_Texture_ScreenNormalMap = -1;
1194 p->tex_Texture_ScreenDiffuse = -1;
1195 p->tex_Texture_ScreenSpecular = -1;
1196 p->tex_Texture_ReflectMask = -1;
1197 p->tex_Texture_ReflectCube = -1;
1198 p->tex_Texture_BounceGrid = -1;
1200 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1201 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1202 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1203 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1204 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1205 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1206 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1207 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1209 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1210 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1211 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1212 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1213 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1215 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1216 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1217 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1218 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1219 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1220 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1221 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1222 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1223 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1224 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1226 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1227 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1228 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1229 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1231 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1234 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1238 Mem_Free(vertexstring);
1240 Mem_Free(geometrystring);
1242 Mem_Free(fragmentstring);
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1247 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248 if (r_glsl_permutation != perm)
1250 r_glsl_permutation = perm;
1251 if (!r_glsl_permutation->program)
1253 if (!r_glsl_permutation->compiled)
1254 R_GLSL_CompilePermutation(perm, mode, permutation);
1255 if (!r_glsl_permutation->program)
1257 // remove features until we find a valid permutation
1259 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1261 // reduce i more quickly whenever it would not remove any bits
1262 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263 if (!(permutation & j))
1266 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267 if (!r_glsl_permutation->compiled)
1268 R_GLSL_CompilePermutation(perm, mode, permutation);
1269 if (r_glsl_permutation->program)
1272 if (i >= SHADERPERMUTATION_COUNT)
1274 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276 qglUseProgram(0);CHECKGLERROR
1277 return; // no bit left to clear, entire mode is broken
1282 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1284 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1300 /// hash lookup data
1301 struct r_hlsl_permutation_s *hashnext;
1303 unsigned int permutation;
1305 /// indicates if we have tried compiling this permutation already
1307 /// NULL if compilation failed
1308 IDirect3DVertexShader9 *vertexshader;
1309 IDirect3DPixelShader9 *pixelshader;
1311 r_hlsl_permutation_t;
1313 typedef enum D3DVSREGISTER_e
1315 D3DVSREGISTER_TexMatrix = 0, // float4x4
1316 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320 D3DVSREGISTER_ModelToLight = 20, // float4x4
1321 D3DVSREGISTER_EyePosition = 24,
1322 D3DVSREGISTER_FogPlane = 25,
1323 D3DVSREGISTER_LightDir = 26,
1324 D3DVSREGISTER_LightPosition = 27,
1328 typedef enum D3DPSREGISTER_e
1330 D3DPSREGISTER_Alpha = 0,
1331 D3DPSREGISTER_BloomBlur_Parameters = 1,
1332 D3DPSREGISTER_ClientTime = 2,
1333 D3DPSREGISTER_Color_Ambient = 3,
1334 D3DPSREGISTER_Color_Diffuse = 4,
1335 D3DPSREGISTER_Color_Specular = 5,
1336 D3DPSREGISTER_Color_Glow = 6,
1337 D3DPSREGISTER_Color_Pants = 7,
1338 D3DPSREGISTER_Color_Shirt = 8,
1339 D3DPSREGISTER_DeferredColor_Ambient = 9,
1340 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341 D3DPSREGISTER_DeferredColor_Specular = 11,
1342 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343 D3DPSREGISTER_DeferredMod_Specular = 13,
1344 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345 D3DPSREGISTER_EyePosition = 15, // unused
1346 D3DPSREGISTER_FogColor = 16,
1347 D3DPSREGISTER_FogHeightFade = 17,
1348 D3DPSREGISTER_FogPlane = 18,
1349 D3DPSREGISTER_FogPlaneViewDist = 19,
1350 D3DPSREGISTER_FogRangeRecip = 20,
1351 D3DPSREGISTER_LightColor = 21,
1352 D3DPSREGISTER_LightDir = 22, // unused
1353 D3DPSREGISTER_LightPosition = 23,
1354 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355 D3DPSREGISTER_PixelSize = 25,
1356 D3DPSREGISTER_ReflectColor = 26,
1357 D3DPSREGISTER_ReflectFactor = 27,
1358 D3DPSREGISTER_ReflectOffset = 28,
1359 D3DPSREGISTER_RefractColor = 29,
1360 D3DPSREGISTER_Saturation = 30,
1361 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363 D3DPSREGISTER_ScreenToDepth = 33,
1364 D3DPSREGISTER_ShadowMap_Parameters = 34,
1365 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366 D3DPSREGISTER_SpecularPower = 36,
1367 D3DPSREGISTER_UserVec1 = 37,
1368 D3DPSREGISTER_UserVec2 = 38,
1369 D3DPSREGISTER_UserVec3 = 39,
1370 D3DPSREGISTER_UserVec4 = 40,
1371 D3DPSREGISTER_ViewTintColor = 41,
1372 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373 D3DPSREGISTER_BloomColorSubtract = 43,
1374 D3DPSREGISTER_ViewToLight = 44, // float4x4
1375 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376 D3DPSREGISTER_NormalmapScrollBlend = 52,
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1390 //unsigned int hashdepth = 0;
1391 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392 r_hlsl_permutation_t *p;
1393 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1395 if (p->mode == mode && p->permutation == permutation)
1397 //if (hashdepth > 10)
1398 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1403 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1405 p->permutation = permutation;
1406 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407 r_hlsl_permutationhash[mode][hashindex] = p;
1408 //if (hashdepth > 10)
1409 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1416 if (!filename || !filename[0])
1418 if (!strcmp(filename, "hlsl/default.hlsl"))
1420 if (!hlslshaderstring)
1422 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423 if (hlslshaderstring)
1424 Con_DPrintf("Loading shaders from file %s...\n", filename);
1426 hlslshaderstring = (char *)builtinhlslshaderstring;
1428 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430 return shaderstring;
1432 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1435 if (printfromdisknotice)
1436 Con_DPrintf("from disk %s... ", filename);
1437 return shaderstring;
1439 return shaderstring;
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1448 DWORD *vsbin = NULL;
1449 DWORD *psbin = NULL;
1450 fs_offset_t vsbinsize;
1451 fs_offset_t psbinsize;
1452 // IDirect3DVertexShader9 *vs = NULL;
1453 // IDirect3DPixelShader9 *ps = NULL;
1454 ID3DXBuffer *vslog = NULL;
1455 ID3DXBuffer *vsbuffer = NULL;
1456 ID3DXConstantTable *vsconstanttable = NULL;
1457 ID3DXBuffer *pslog = NULL;
1458 ID3DXBuffer *psbuffer = NULL;
1459 ID3DXConstantTable *psconstanttable = NULL;
1462 char temp[MAX_INPUTLINE];
1463 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464 qboolean debugshader = gl_paranoid.integer != 0;
1465 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1469 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1472 if ((!vsbin && vertstring) || (!psbin && fragstring))
1474 const char* dllnames_d3dx9 [] =
1498 dllhandle_t d3dx9_dll = NULL;
1499 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502 dllfunction_t d3dx9_dllfuncs[] =
1504 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1505 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1506 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1509 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1511 DWORD shaderflags = 0;
1513 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516 if (vertstring && vertstring[0])
1520 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1526 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529 vsbinsize = vsbuffer->GetBufferSize();
1530 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532 vsbuffer->Release();
1536 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1541 if (fragstring && fragstring[0])
1545 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1551 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554 psbinsize = psbuffer->GetBufferSize();
1555 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557 psbuffer->Release();
1561 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1566 Sys_UnloadLibrary(&d3dx9_dll);
1569 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1573 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574 if (FAILED(vsresult))
1575 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577 if (FAILED(psresult))
1578 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1580 // free the shader data
1581 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1588 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589 int vertstring_length = 0;
1590 int geomstring_length = 0;
1591 int fragstring_length = 0;
1593 char *vertexstring, *geometrystring, *fragmentstring;
1594 char *vertstring, *geomstring, *fragstring;
1595 char permutationname[256];
1596 char cachename[256];
1597 int vertstrings_count = 0;
1598 int geomstrings_count = 0;
1599 int fragstrings_count = 0;
1600 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607 p->vertexshader = NULL;
1608 p->pixelshader = NULL;
1610 permutationname[0] = 0;
1612 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1616 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617 strlcat(cachename, "hlsl/", sizeof(cachename));
1619 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620 vertstrings_count = 0;
1621 geomstrings_count = 0;
1622 fragstrings_count = 0;
1623 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1627 // the first pretext is which type of shader to compile as
1628 // (later these will all be bound together as a program object)
1629 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1633 // the second pretext is the mode (for example a light source)
1634 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638 strlcat(cachename, modeinfo->name, sizeof(cachename));
1640 // now add all the permutation pretexts
1641 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1643 if (permutation & (1<<i))
1645 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1653 // keep line numbers correct
1654 vertstrings_list[vertstrings_count++] = "\n";
1655 geomstrings_list[geomstrings_count++] = "\n";
1656 fragstrings_list[fragstrings_count++] = "\n";
1661 R_CompileShader_AddStaticParms(mode, permutation);
1662 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663 vertstrings_count += shaderstaticparms_count;
1664 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665 geomstrings_count += shaderstaticparms_count;
1666 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667 fragstrings_count += shaderstaticparms_count;
1669 // replace spaces in the cachename with _ characters
1670 for (i = 0;cachename[i];i++)
1671 if (cachename[i] == ' ')
1674 // now append the shader text itself
1675 vertstrings_list[vertstrings_count++] = vertexstring;
1676 geomstrings_list[geomstrings_count++] = geometrystring;
1677 fragstrings_list[fragstrings_count++] = fragmentstring;
1679 // if any sources were NULL, clear the respective list
1681 vertstrings_count = 0;
1682 if (!geometrystring)
1683 geomstrings_count = 0;
1684 if (!fragmentstring)
1685 fragstrings_count = 0;
1687 vertstring_length = 0;
1688 for (i = 0;i < vertstrings_count;i++)
1689 vertstring_length += strlen(vertstrings_list[i]);
1690 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1694 geomstring_length = 0;
1695 for (i = 0;i < geomstrings_count;i++)
1696 geomstring_length += strlen(geomstrings_list[i]);
1697 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1701 fragstring_length = 0;
1702 for (i = 0;i < fragstrings_count;i++)
1703 fragstring_length += strlen(fragstrings_list[i]);
1704 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1708 // try to load the cached shader, or generate one
1709 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1711 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1714 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1718 Mem_Free(vertstring);
1720 Mem_Free(geomstring);
1722 Mem_Free(fragstring);
1724 Mem_Free(vertexstring);
1726 Mem_Free(geometrystring);
1728 Mem_Free(fragmentstring);
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 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);}
1734 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);}
1735 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);}
1736 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);}
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 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);}
1741 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);}
1742 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);}
1743 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);}
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1747 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748 if (r_hlsl_permutation != perm)
1750 r_hlsl_permutation = perm;
1751 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1753 if (!r_hlsl_permutation->compiled)
1754 R_HLSL_CompilePermutation(perm, mode, permutation);
1755 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757 // remove features until we find a valid permutation
1759 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1761 // reduce i more quickly whenever it would not remove any bits
1762 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763 if (!(permutation & j))
1766 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767 if (!r_hlsl_permutation->compiled)
1768 R_HLSL_CompilePermutation(perm, mode, permutation);
1769 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1772 if (i >= SHADERPERMUTATION_COUNT)
1774 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776 return; // no bit left to clear, entire mode is broken
1780 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1783 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1791 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1797 void R_GLSL_Restart_f(void)
1799 unsigned int i, limit;
1800 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801 Mem_Free(glslshaderstring);
1802 glslshaderstring = NULL;
1803 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804 Mem_Free(hlslshaderstring);
1805 hlslshaderstring = NULL;
1806 switch(vid.renderpath)
1808 case RENDERPATH_D3D9:
1811 r_hlsl_permutation_t *p;
1812 r_hlsl_permutation = NULL;
1813 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814 for (i = 0;i < limit;i++)
1816 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1818 if (p->vertexshader)
1819 IDirect3DVertexShader9_Release(p->vertexshader);
1821 IDirect3DPixelShader9_Release(p->pixelshader);
1822 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1825 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1829 case RENDERPATH_D3D10:
1830 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832 case RENDERPATH_D3D11:
1833 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835 case RENDERPATH_GL20:
1836 case RENDERPATH_GLES2:
1838 r_glsl_permutation_t *p;
1839 r_glsl_permutation = NULL;
1840 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841 for (i = 0;i < limit;i++)
1843 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1845 GL_Backend_FreeProgram(p->program);
1846 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1849 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1852 case RENDERPATH_GL11:
1853 case RENDERPATH_GL13:
1854 case RENDERPATH_GLES1:
1856 case RENDERPATH_SOFT:
1861 void R_GLSL_DumpShader_f(void)
1866 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1869 FS_Print(file, "/* The engine may define the following macros:\n");
1870 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871 for (i = 0;i < SHADERMODE_COUNT;i++)
1872 FS_Print(file, glslshadermodeinfo[i].pretext);
1873 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874 FS_Print(file, shaderpermutationinfo[i].pretext);
1875 FS_Print(file, "*/\n");
1876 FS_Print(file, builtinshaderstring);
1878 Con_Printf("glsl/default.glsl written\n");
1881 Con_Printf("failed to write to glsl/default.glsl\n");
1883 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1886 FS_Print(file, "/* The engine may define the following macros:\n");
1887 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1888 for (i = 0;i < SHADERMODE_COUNT;i++)
1889 FS_Print(file, hlslshadermodeinfo[i].pretext);
1890 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1891 FS_Print(file, shaderpermutationinfo[i].pretext);
1892 FS_Print(file, "*/\n");
1893 FS_Print(file, builtinhlslshaderstring);
1895 Con_Printf("hlsl/default.hlsl written\n");
1898 Con_Printf("failed to write to hlsl/default.hlsl\n");
1901 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
1903 unsigned int permutation = 0;
1904 if (r_trippy.integer && !notrippy)
1905 permutation |= SHADERPERMUTATION_TRIPPY;
1906 permutation |= SHADERPERMUTATION_VIEWTINT;
1908 permutation |= SHADERPERMUTATION_DIFFUSE;
1910 permutation |= SHADERPERMUTATION_SPECULAR;
1911 if (texturemode == GL_MODULATE)
1912 permutation |= SHADERPERMUTATION_COLORMAPPING;
1913 else if (texturemode == GL_ADD)
1914 permutation |= SHADERPERMUTATION_GLOW;
1915 else if (texturemode == GL_DECAL)
1916 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1918 texturemode = GL_MODULATE;
1919 if (vid.allowalphatocoverage)
1920 GL_AlphaToCoverage(false);
1921 switch (vid.renderpath)
1923 case RENDERPATH_D3D9:
1925 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1926 R_Mesh_TexBind(GL20TU_FIRST , first );
1927 R_Mesh_TexBind(GL20TU_SECOND, second);
1930 case RENDERPATH_D3D10:
1931 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1933 case RENDERPATH_D3D11:
1934 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1936 case RENDERPATH_GL20:
1937 case RENDERPATH_GLES2:
1938 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1939 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1940 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1942 case RENDERPATH_GL13:
1943 case RENDERPATH_GLES1:
1944 R_Mesh_TexBind(0, first );
1945 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1946 R_Mesh_TexBind(1, second);
1948 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1950 case RENDERPATH_GL11:
1951 R_Mesh_TexBind(0, first );
1953 case RENDERPATH_SOFT:
1954 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1955 R_Mesh_TexBind(GL20TU_FIRST , first );
1956 R_Mesh_TexBind(GL20TU_SECOND, second);
1961 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1963 unsigned int permutation = 0;
1964 if (r_trippy.integer && !notrippy)
1965 permutation |= SHADERPERMUTATION_TRIPPY;
1966 if (vid.allowalphatocoverage)
1967 GL_AlphaToCoverage(false);
1968 switch (vid.renderpath)
1970 case RENDERPATH_D3D9:
1972 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1975 case RENDERPATH_D3D10:
1976 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1978 case RENDERPATH_D3D11:
1979 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1981 case RENDERPATH_GL20:
1982 case RENDERPATH_GLES2:
1983 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1985 case RENDERPATH_GL13:
1986 case RENDERPATH_GLES1:
1987 R_Mesh_TexBind(0, 0);
1988 R_Mesh_TexBind(1, 0);
1990 case RENDERPATH_GL11:
1991 R_Mesh_TexBind(0, 0);
1993 case RENDERPATH_SOFT:
1994 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1999 void R_SetupShader_ShowDepth(qboolean notrippy)
2001 int permutation = 0;
2002 if (r_trippy.integer && !notrippy)
2003 permutation |= SHADERPERMUTATION_TRIPPY;
2004 if (r_trippy.integer)
2005 permutation |= SHADERPERMUTATION_TRIPPY;
2006 if (vid.allowalphatocoverage)
2007 GL_AlphaToCoverage(false);
2008 switch (vid.renderpath)
2010 case RENDERPATH_D3D9:
2012 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2015 case RENDERPATH_D3D10:
2016 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2018 case RENDERPATH_D3D11:
2019 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2021 case RENDERPATH_GL20:
2022 case RENDERPATH_GLES2:
2023 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2025 case RENDERPATH_GL13:
2026 case RENDERPATH_GLES1:
2028 case RENDERPATH_GL11:
2030 case RENDERPATH_SOFT:
2031 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2036 extern qboolean r_shadow_usingdeferredprepass;
2037 extern cvar_t r_shadow_deferred_8bitrange;
2038 extern rtexture_t *r_shadow_attenuationgradienttexture;
2039 extern rtexture_t *r_shadow_attenuation2dtexture;
2040 extern rtexture_t *r_shadow_attenuation3dtexture;
2041 extern qboolean r_shadow_usingshadowmap2d;
2042 extern qboolean r_shadow_usingshadowmaportho;
2043 extern float r_shadow_shadowmap_texturescale[2];
2044 extern float r_shadow_shadowmap_parameters[4];
2045 extern qboolean r_shadow_shadowmapvsdct;
2046 extern qboolean r_shadow_shadowmapsampler;
2047 extern int r_shadow_shadowmappcf;
2048 extern rtexture_t *r_shadow_shadowmap2dtexture;
2049 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2050 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2051 extern matrix4x4_t r_shadow_shadowmapmatrix;
2052 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2053 extern int r_shadow_prepass_width;
2054 extern int r_shadow_prepass_height;
2055 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2056 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2057 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2058 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2059 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2061 #define BLENDFUNC_ALLOWS_COLORMOD 1
2062 #define BLENDFUNC_ALLOWS_FOG 2
2063 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2064 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2065 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2066 static int R_BlendFuncFlags(int src, int dst)
2070 // a blendfunc allows colormod if:
2071 // a) it can never keep the destination pixel invariant, or
2072 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2073 // this is to prevent unintended side effects from colormod
2075 // a blendfunc allows fog if:
2076 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2077 // this is to prevent unintended side effects from fog
2079 // these checks are the output of fogeval.pl
2081 r |= BLENDFUNC_ALLOWS_COLORMOD;
2082 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2083 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2084 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2086 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2089 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2090 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2091 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2092 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2095 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2096 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2097 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2100 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2101 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2102 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107 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)
2109 // select a permutation of the lighting shader appropriate to this
2110 // combination of texture, entity, light source, and fogging, only use the
2111 // minimum features necessary to avoid wasting rendering time in the
2112 // fragment shader on features that are not being used
2113 unsigned int permutation = 0;
2114 unsigned int mode = 0;
2116 static float dummy_colormod[3] = {1, 1, 1};
2117 float *colormod = rsurface.colormod;
2119 matrix4x4_t tempmatrix;
2120 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2121 if (r_trippy.integer && !notrippy)
2122 permutation |= SHADERPERMUTATION_TRIPPY;
2123 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2124 permutation |= SHADERPERMUTATION_ALPHAKILL;
2125 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2126 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2127 if (rsurfacepass == RSURFPASS_BACKGROUND)
2129 // distorted background
2130 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2132 mode = SHADERMODE_WATER;
2133 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2135 // this is the right thing to do for wateralpha
2136 GL_BlendFunc(GL_ONE, GL_ZERO);
2137 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2141 // this is the right thing to do for entity alpha
2142 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2143 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2148 mode = SHADERMODE_REFRACTION;
2149 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2150 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154 mode = SHADERMODE_GENERIC;
2155 permutation |= SHADERPERMUTATION_DIFFUSE;
2156 GL_BlendFunc(GL_ONE, GL_ZERO);
2157 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2159 if (vid.allowalphatocoverage)
2160 GL_AlphaToCoverage(false);
2162 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2164 if (r_glsl_offsetmapping.integer)
2166 switch(rsurface.texture->offsetmapping)
2168 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2169 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2170 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2171 case OFFSETMAPPING_OFF: break;
2174 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2175 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2176 // normalmap (deferred prepass), may use alpha test on diffuse
2177 mode = SHADERMODE_DEFERREDGEOMETRY;
2178 GL_BlendFunc(GL_ONE, GL_ZERO);
2179 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2180 if (vid.allowalphatocoverage)
2181 GL_AlphaToCoverage(false);
2183 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2185 if (r_glsl_offsetmapping.integer)
2187 switch(rsurface.texture->offsetmapping)
2189 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2190 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2191 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2192 case OFFSETMAPPING_OFF: break;
2195 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2196 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2198 mode = SHADERMODE_LIGHTSOURCE;
2199 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2200 permutation |= SHADERPERMUTATION_CUBEFILTER;
2201 if (diffusescale > 0)
2202 permutation |= SHADERPERMUTATION_DIFFUSE;
2203 if (specularscale > 0)
2204 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2205 if (r_refdef.fogenabled)
2206 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2207 if (rsurface.texture->colormapping)
2208 permutation |= SHADERPERMUTATION_COLORMAPPING;
2209 if (r_shadow_usingshadowmap2d)
2211 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2212 if(r_shadow_shadowmapvsdct)
2213 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2215 if (r_shadow_shadowmapsampler)
2216 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2217 if (r_shadow_shadowmappcf > 1)
2218 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2219 else if (r_shadow_shadowmappcf)
2220 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2222 if (rsurface.texture->reflectmasktexture)
2223 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2224 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2225 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2226 if (vid.allowalphatocoverage)
2227 GL_AlphaToCoverage(false);
2229 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2231 if (r_glsl_offsetmapping.integer)
2233 switch(rsurface.texture->offsetmapping)
2235 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2236 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2237 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2238 case OFFSETMAPPING_OFF: break;
2241 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2242 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2243 // unshaded geometry (fullbright or ambient model lighting)
2244 mode = SHADERMODE_FLATCOLOR;
2245 ambientscale = diffusescale = specularscale = 0;
2246 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2247 permutation |= SHADERPERMUTATION_GLOW;
2248 if (r_refdef.fogenabled)
2249 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2250 if (rsurface.texture->colormapping)
2251 permutation |= SHADERPERMUTATION_COLORMAPPING;
2252 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2254 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2255 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2257 if (r_shadow_shadowmapsampler)
2258 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2259 if (r_shadow_shadowmappcf > 1)
2260 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2261 else if (r_shadow_shadowmappcf)
2262 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2264 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2265 permutation |= SHADERPERMUTATION_REFLECTION;
2266 if (rsurface.texture->reflectmasktexture)
2267 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2268 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2269 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2270 // when using alphatocoverage, we don't need alphakill
2271 if (vid.allowalphatocoverage)
2273 if (r_transparent_alphatocoverage.integer)
2275 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2276 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2279 GL_AlphaToCoverage(false);
2282 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2284 if (r_glsl_offsetmapping.integer)
2286 switch(rsurface.texture->offsetmapping)
2288 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2289 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291 case OFFSETMAPPING_OFF: break;
2294 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2295 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2296 // directional model lighting
2297 mode = SHADERMODE_LIGHTDIRECTION;
2298 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2299 permutation |= SHADERPERMUTATION_GLOW;
2300 permutation |= SHADERPERMUTATION_DIFFUSE;
2301 if (specularscale > 0)
2302 permutation |= SHADERPERMUTATION_SPECULAR;
2303 if (r_refdef.fogenabled)
2304 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2305 if (rsurface.texture->colormapping)
2306 permutation |= SHADERPERMUTATION_COLORMAPPING;
2307 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2309 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2310 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2312 if (r_shadow_shadowmapsampler)
2313 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2314 if (r_shadow_shadowmappcf > 1)
2315 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2316 else if (r_shadow_shadowmappcf)
2317 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2319 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2320 permutation |= SHADERPERMUTATION_REFLECTION;
2321 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2322 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2323 if (rsurface.texture->reflectmasktexture)
2324 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2325 if (r_shadow_bouncegridtexture)
2327 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2328 if (r_shadow_bouncegriddirectional)
2329 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2331 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2332 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2333 // when using alphatocoverage, we don't need alphakill
2334 if (vid.allowalphatocoverage)
2336 if (r_transparent_alphatocoverage.integer)
2338 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2339 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2342 GL_AlphaToCoverage(false);
2345 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2347 if (r_glsl_offsetmapping.integer)
2349 switch(rsurface.texture->offsetmapping)
2351 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2352 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2353 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2354 case OFFSETMAPPING_OFF: break;
2357 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2358 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2359 // ambient model lighting
2360 mode = SHADERMODE_LIGHTDIRECTION;
2361 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2362 permutation |= SHADERPERMUTATION_GLOW;
2363 if (r_refdef.fogenabled)
2364 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2365 if (rsurface.texture->colormapping)
2366 permutation |= SHADERPERMUTATION_COLORMAPPING;
2367 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2369 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2370 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2372 if (r_shadow_shadowmapsampler)
2373 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2374 if (r_shadow_shadowmappcf > 1)
2375 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2376 else if (r_shadow_shadowmappcf)
2377 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2379 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2380 permutation |= SHADERPERMUTATION_REFLECTION;
2381 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2382 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2383 if (rsurface.texture->reflectmasktexture)
2384 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2385 if (r_shadow_bouncegridtexture)
2387 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2388 if (r_shadow_bouncegriddirectional)
2389 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2391 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2392 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2393 // when using alphatocoverage, we don't need alphakill
2394 if (vid.allowalphatocoverage)
2396 if (r_transparent_alphatocoverage.integer)
2398 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2399 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2402 GL_AlphaToCoverage(false);
2407 if (r_glsl_offsetmapping.integer)
2409 switch(rsurface.texture->offsetmapping)
2411 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2412 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2413 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2414 case OFFSETMAPPING_OFF: break;
2417 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2418 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2420 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2421 permutation |= SHADERPERMUTATION_GLOW;
2422 if (r_refdef.fogenabled)
2423 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2424 if (rsurface.texture->colormapping)
2425 permutation |= SHADERPERMUTATION_COLORMAPPING;
2426 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2428 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2429 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2431 if (r_shadow_shadowmapsampler)
2432 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2433 if (r_shadow_shadowmappcf > 1)
2434 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2435 else if (r_shadow_shadowmappcf)
2436 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2438 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2439 permutation |= SHADERPERMUTATION_REFLECTION;
2440 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2441 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2442 if (rsurface.texture->reflectmasktexture)
2443 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2444 if (FAKELIGHT_ENABLED)
2446 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2447 mode = SHADERMODE_FAKELIGHT;
2448 permutation |= SHADERPERMUTATION_DIFFUSE;
2449 if (specularscale > 0)
2450 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2452 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2454 // deluxemapping (light direction texture)
2455 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2456 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2458 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2459 permutation |= SHADERPERMUTATION_DIFFUSE;
2460 if (specularscale > 0)
2461 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2463 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2465 // fake deluxemapping (uniform light direction in tangentspace)
2466 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2467 permutation |= SHADERPERMUTATION_DIFFUSE;
2468 if (specularscale > 0)
2469 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2471 else if (rsurface.uselightmaptexture)
2473 // ordinary lightmapping (q1bsp, q3bsp)
2474 mode = SHADERMODE_LIGHTMAP;
2478 // ordinary vertex coloring (q3bsp)
2479 mode = SHADERMODE_VERTEXCOLOR;
2481 if (r_shadow_bouncegridtexture)
2483 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2484 if (r_shadow_bouncegriddirectional)
2485 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2487 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2488 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2489 // when using alphatocoverage, we don't need alphakill
2490 if (vid.allowalphatocoverage)
2492 if (r_transparent_alphatocoverage.integer)
2494 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2495 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2498 GL_AlphaToCoverage(false);
2501 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2502 colormod = dummy_colormod;
2503 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2504 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2505 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2506 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2507 switch(vid.renderpath)
2509 case RENDERPATH_D3D9:
2511 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);
2512 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2513 R_SetupShader_SetPermutationHLSL(mode, permutation);
2514 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2515 if (mode == SHADERMODE_LIGHTSOURCE)
2517 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2518 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2522 if (mode == SHADERMODE_LIGHTDIRECTION)
2524 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2527 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2528 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2529 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2530 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2531 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2533 if (mode == SHADERMODE_LIGHTSOURCE)
2535 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2536 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2537 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2538 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2539 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2541 // additive passes are only darkened by fog, not tinted
2542 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2543 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2547 if (mode == SHADERMODE_FLATCOLOR)
2549 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2551 else if (mode == SHADERMODE_LIGHTDIRECTION)
2553 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]);
2554 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2555 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);
2556 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);
2557 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2558 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2559 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2563 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2564 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2565 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);
2566 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);
2567 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2569 // additive passes are only darkened by fog, not tinted
2570 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2571 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2573 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2574 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);
2575 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2576 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2577 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2578 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2579 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2580 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2581 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2582 if (mode == SHADERMODE_WATER)
2583 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2585 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2586 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2587 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2588 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));
2589 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2590 if (rsurface.texture->pantstexture)
2591 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2593 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2594 if (rsurface.texture->shirttexture)
2595 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2597 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2598 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2599 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2600 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2601 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2602 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2603 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2604 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2605 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2606 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2608 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2609 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2611 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2612 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2613 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2614 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2615 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2616 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2617 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2618 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2619 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2620 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2621 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2622 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2623 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2624 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2625 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2626 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2627 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2628 if (rsurfacepass == RSURFPASS_BACKGROUND)
2630 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2631 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2632 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2636 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2638 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2639 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2640 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2641 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2642 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2644 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2645 if (rsurface.rtlight)
2647 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2648 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2653 case RENDERPATH_D3D10:
2654 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2656 case RENDERPATH_D3D11:
2657 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2659 case RENDERPATH_GL20:
2660 case RENDERPATH_GLES2:
2661 if (!vid.useinterleavedarrays)
2663 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);
2664 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2665 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2666 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2667 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2668 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2669 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2670 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2674 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);
2675 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2677 R_SetupShader_SetPermutationGLSL(mode, permutation);
2678 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2679 if (mode == SHADERMODE_LIGHTSOURCE)
2681 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2682 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2683 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2684 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2685 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2686 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);
2688 // additive passes are only darkened by fog, not tinted
2689 if (r_glsl_permutation->loc_FogColor >= 0)
2690 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2691 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2695 if (mode == SHADERMODE_FLATCOLOR)
2697 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2699 else if (mode == SHADERMODE_LIGHTDIRECTION)
2701 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]);
2702 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]);
2703 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);
2704 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);
2705 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);
2706 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]);
2707 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]);
2711 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]);
2712 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]);
2713 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);
2714 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);
2715 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);
2717 // additive passes are only darkened by fog, not tinted
2718 if (r_glsl_permutation->loc_FogColor >= 0)
2720 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2721 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2723 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2725 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);
2726 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]);
2727 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]);
2728 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]);
2729 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]);
2730 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2731 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2732 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2733 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]);
2735 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2736 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2737 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2738 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]);
2739 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]);
2741 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2742 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));
2743 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2744 if (r_glsl_permutation->loc_Color_Pants >= 0)
2746 if (rsurface.texture->pantstexture)
2747 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2749 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2751 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2753 if (rsurface.texture->shirttexture)
2754 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2756 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2758 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]);
2759 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2760 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2761 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2762 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2763 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2764 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2765 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2766 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2768 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]);
2769 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2770 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);}
2771 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2773 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2774 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2775 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2776 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2777 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2778 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2779 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2780 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2781 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2782 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2783 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2784 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2785 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2786 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2787 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);
2788 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2789 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2790 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2791 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2792 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2793 if (rsurfacepass == RSURFPASS_BACKGROUND)
2795 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);
2796 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);
2797 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);
2801 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);
2803 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2804 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2805 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2806 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2807 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2809 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2810 if (rsurface.rtlight)
2812 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2813 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2816 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2819 case RENDERPATH_GL11:
2820 case RENDERPATH_GL13:
2821 case RENDERPATH_GLES1:
2823 case RENDERPATH_SOFT:
2824 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);
2825 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2826 R_SetupShader_SetPermutationSoft(mode, permutation);
2827 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2828 if (mode == SHADERMODE_LIGHTSOURCE)
2830 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2831 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2832 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2833 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2834 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2835 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2837 // additive passes are only darkened by fog, not tinted
2838 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2839 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2843 if (mode == SHADERMODE_FLATCOLOR)
2845 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2847 else if (mode == SHADERMODE_LIGHTDIRECTION)
2849 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]);
2850 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2851 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);
2852 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);
2853 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2854 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]);
2855 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2859 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2860 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2861 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);
2862 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);
2863 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2865 // additive passes are only darkened by fog, not tinted
2866 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2867 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2869 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2870 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);
2871 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2872 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2873 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]);
2874 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]);
2875 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2876 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2877 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2878 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2880 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2881 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2882 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2883 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2884 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]);
2886 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2887 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));
2888 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2889 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2891 if (rsurface.texture->pantstexture)
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2894 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2896 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2898 if (rsurface.texture->shirttexture)
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2901 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2903 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2904 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2905 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2906 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2907 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2908 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2909 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2910 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2911 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2913 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2914 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2916 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2917 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2918 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2919 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2920 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2921 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2922 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2923 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2924 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2925 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2926 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2927 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2928 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2929 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2930 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2931 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2932 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2933 if (rsurfacepass == RSURFPASS_BACKGROUND)
2935 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2936 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2937 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2941 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2943 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2944 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2945 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2946 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2947 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2949 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2950 if (rsurface.rtlight)
2952 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2953 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2960 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2962 // select a permutation of the lighting shader appropriate to this
2963 // combination of texture, entity, light source, and fogging, only use the
2964 // minimum features necessary to avoid wasting rendering time in the
2965 // fragment shader on features that are not being used
2966 unsigned int permutation = 0;
2967 unsigned int mode = 0;
2968 const float *lightcolorbase = rtlight->currentcolor;
2969 float ambientscale = rtlight->ambientscale;
2970 float diffusescale = rtlight->diffusescale;
2971 float specularscale = rtlight->specularscale;
2972 // this is the location of the light in view space
2973 vec3_t viewlightorigin;
2974 // this transforms from view space (camera) to light space (cubemap)
2975 matrix4x4_t viewtolight;
2976 matrix4x4_t lighttoview;
2977 float viewtolight16f[16];
2978 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2980 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2981 if (rtlight->currentcubemap != r_texture_whitecube)
2982 permutation |= SHADERPERMUTATION_CUBEFILTER;
2983 if (diffusescale > 0)
2984 permutation |= SHADERPERMUTATION_DIFFUSE;
2985 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2986 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2987 if (r_shadow_usingshadowmap2d)
2989 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2990 if (r_shadow_shadowmapvsdct)
2991 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2993 if (r_shadow_shadowmapsampler)
2994 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2995 if (r_shadow_shadowmappcf > 1)
2996 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2997 else if (r_shadow_shadowmappcf)
2998 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3000 if (vid.allowalphatocoverage)
3001 GL_AlphaToCoverage(false);
3002 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3003 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3004 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3005 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3006 switch(vid.renderpath)
3008 case RENDERPATH_D3D9:
3010 R_SetupShader_SetPermutationHLSL(mode, permutation);
3011 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3012 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3013 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3014 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3015 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3016 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3017 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3018 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3019 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3020 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3022 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3023 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3024 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3025 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3026 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3027 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3030 case RENDERPATH_D3D10:
3031 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3033 case RENDERPATH_D3D11:
3034 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3036 case RENDERPATH_GL20:
3037 case RENDERPATH_GLES2:
3038 R_SetupShader_SetPermutationGLSL(mode, permutation);
3039 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3040 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3041 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);
3042 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);
3043 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);
3044 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]);
3045 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]);
3046 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));
3047 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]);
3048 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3050 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3051 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3052 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3053 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3054 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3055 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3057 case RENDERPATH_GL11:
3058 case RENDERPATH_GL13:
3059 case RENDERPATH_GLES1:
3061 case RENDERPATH_SOFT:
3062 R_SetupShader_SetPermutationGLSL(mode, permutation);
3063 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3064 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3065 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3066 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3067 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3068 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3069 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]);
3070 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));
3071 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3072 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3074 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3075 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3076 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3077 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3078 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3079 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3084 #define SKINFRAME_HASH 1024
3088 int loadsequence; // incremented each level change
3089 memexpandablearray_t array;
3090 skinframe_t *hash[SKINFRAME_HASH];
3093 r_skinframe_t r_skinframe;
3095 void R_SkinFrame_PrepareForPurge(void)
3097 r_skinframe.loadsequence++;
3098 // wrap it without hitting zero
3099 if (r_skinframe.loadsequence >= 200)
3100 r_skinframe.loadsequence = 1;
3103 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3107 // mark the skinframe as used for the purging code
3108 skinframe->loadsequence = r_skinframe.loadsequence;
3111 void R_SkinFrame_Purge(void)
3115 for (i = 0;i < SKINFRAME_HASH;i++)
3117 for (s = r_skinframe.hash[i];s;s = s->next)
3119 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3121 if (s->merged == s->base)
3123 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3124 R_PurgeTexture(s->stain );s->stain = NULL;
3125 R_PurgeTexture(s->merged);s->merged = NULL;
3126 R_PurgeTexture(s->base );s->base = NULL;
3127 R_PurgeTexture(s->pants );s->pants = NULL;
3128 R_PurgeTexture(s->shirt );s->shirt = NULL;
3129 R_PurgeTexture(s->nmap );s->nmap = NULL;
3130 R_PurgeTexture(s->gloss );s->gloss = NULL;
3131 R_PurgeTexture(s->glow );s->glow = NULL;
3132 R_PurgeTexture(s->fog );s->fog = NULL;
3133 R_PurgeTexture(s->reflect);s->reflect = NULL;
3134 s->loadsequence = 0;
3140 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3142 char basename[MAX_QPATH];
3144 Image_StripImageExtension(name, basename, sizeof(basename));
3146 if( last == NULL ) {
3148 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3149 item = r_skinframe.hash[hashindex];
3154 // linearly search through the hash bucket
3155 for( ; item ; item = item->next ) {
3156 if( !strcmp( item->basename, basename ) ) {
3163 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3167 char basename[MAX_QPATH];
3169 Image_StripImageExtension(name, basename, sizeof(basename));
3171 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3172 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3173 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3177 rtexture_t *dyntexture;
3178 // check whether its a dynamic texture
3179 dyntexture = CL_GetDynTexture( basename );
3180 if (!add && !dyntexture)
3182 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3183 memset(item, 0, sizeof(*item));
3184 strlcpy(item->basename, basename, sizeof(item->basename));
3185 item->base = dyntexture; // either NULL or dyntexture handle
3186 item->textureflags = textureflags;
3187 item->comparewidth = comparewidth;
3188 item->compareheight = compareheight;
3189 item->comparecrc = comparecrc;
3190 item->next = r_skinframe.hash[hashindex];
3191 r_skinframe.hash[hashindex] = item;
3193 else if( item->base == NULL )
3195 rtexture_t *dyntexture;
3196 // check whether its a dynamic texture
3197 // 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]
3198 dyntexture = CL_GetDynTexture( basename );
3199 item->base = dyntexture; // either NULL or dyntexture handle
3202 R_SkinFrame_MarkUsed(item);
3206 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3208 unsigned long long avgcolor[5], wsum; \
3216 for(pix = 0; pix < cnt; ++pix) \
3219 for(comp = 0; comp < 3; ++comp) \
3221 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3224 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3226 for(comp = 0; comp < 3; ++comp) \
3227 avgcolor[comp] += getpixel * w; \
3230 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3231 avgcolor[4] += getpixel; \
3233 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3235 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3236 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3237 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3238 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3241 extern cvar_t gl_picmip;
3242 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3245 unsigned char *pixels;
3246 unsigned char *bumppixels;
3247 unsigned char *basepixels = NULL;
3248 int basepixels_width = 0;
3249 int basepixels_height = 0;
3250 skinframe_t *skinframe;
3251 rtexture_t *ddsbase = NULL;
3252 qboolean ddshasalpha = false;
3253 float ddsavgcolor[4];
3254 char basename[MAX_QPATH];
3255 int miplevel = R_PicmipForFlags(textureflags);
3256 int savemiplevel = miplevel;
3259 if (cls.state == ca_dedicated)
3262 // return an existing skinframe if already loaded
3263 // if loading of the first image fails, don't make a new skinframe as it
3264 // would cause all future lookups of this to be missing
3265 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3266 if (skinframe && skinframe->base)
3269 Image_StripImageExtension(name, basename, sizeof(basename));
3271 // check for DDS texture file first
3272 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3274 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3275 if (basepixels == NULL)
3279 // FIXME handle miplevel
3281 if (developer_loading.integer)
3282 Con_Printf("loading skin \"%s\"\n", name);
3284 // we've got some pixels to store, so really allocate this new texture now
3286 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3287 skinframe->stain = NULL;
3288 skinframe->merged = NULL;
3289 skinframe->base = NULL;
3290 skinframe->pants = NULL;
3291 skinframe->shirt = NULL;
3292 skinframe->nmap = NULL;
3293 skinframe->gloss = NULL;
3294 skinframe->glow = NULL;
3295 skinframe->fog = NULL;
3296 skinframe->reflect = NULL;
3297 skinframe->hasalpha = false;
3301 skinframe->base = ddsbase;
3302 skinframe->hasalpha = ddshasalpha;
3303 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3304 if (r_loadfog && skinframe->hasalpha)
3305 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3306 //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]);
3310 basepixels_width = image_width;
3311 basepixels_height = image_height;
3312 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);
3313 if (textureflags & TEXF_ALPHA)
3315 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3317 if (basepixels[j] < 255)
3319 skinframe->hasalpha = true;
3323 if (r_loadfog && skinframe->hasalpha)
3325 // has transparent pixels
3326 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3327 for (j = 0;j < image_width * image_height * 4;j += 4)
3332 pixels[j+3] = basepixels[j+3];
3334 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);
3338 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3339 //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]);
3340 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3341 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3342 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3343 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3348 mymiplevel = savemiplevel;
3349 if (r_loadnormalmap)
3350 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);
3351 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3353 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3354 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3355 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3356 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3359 // _norm is the name used by tenebrae and has been adopted as standard
3360 if (r_loadnormalmap && skinframe->nmap == NULL)
3362 mymiplevel = savemiplevel;
3363 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3365 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);
3369 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3371 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3372 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3373 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);
3375 Mem_Free(bumppixels);
3377 else if (r_shadow_bumpscale_basetexture.value > 0)
3379 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3380 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3381 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);
3384 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3385 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3388 // _luma is supported only for tenebrae compatibility
3389 // _glow is the preferred name
3390 mymiplevel = savemiplevel;
3391 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))))
3393 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);
3394 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3395 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3396 Mem_Free(pixels);pixels = NULL;
3399 mymiplevel = savemiplevel;
3400 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3402 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);
3403 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3404 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3409 mymiplevel = savemiplevel;
3410 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3412 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);
3413 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3414 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3419 mymiplevel = savemiplevel;
3420 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3422 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);
3423 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3424 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3429 mymiplevel = savemiplevel;
3430 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3432 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);
3433 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3434 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3440 Mem_Free(basepixels);
3445 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3446 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3449 unsigned char *temp1, *temp2;
3450 skinframe_t *skinframe;
3452 if (cls.state == ca_dedicated)
3455 // if already loaded just return it, otherwise make a new skinframe
3456 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3457 if (skinframe && skinframe->base)
3460 skinframe->stain = NULL;
3461 skinframe->merged = NULL;
3462 skinframe->base = NULL;
3463 skinframe->pants = NULL;
3464 skinframe->shirt = NULL;
3465 skinframe->nmap = NULL;
3466 skinframe->gloss = NULL;
3467 skinframe->glow = NULL;
3468 skinframe->fog = NULL;
3469 skinframe->reflect = NULL;
3470 skinframe->hasalpha = false;
3472 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3476 if (developer_loading.integer)
3477 Con_Printf("loading 32bit skin \"%s\"\n", name);
3479 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3481 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3482 temp2 = temp1 + width * height * 4;
3483 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3484 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);
3487 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3488 if (textureflags & TEXF_ALPHA)
3490 for (i = 3;i < width * height * 4;i += 4)
3492 if (skindata[i] < 255)
3494 skinframe->hasalpha = true;
3498 if (r_loadfog && skinframe->hasalpha)
3500 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3501 memcpy(fogpixels, skindata, width * height * 4);
3502 for (i = 0;i < width * height * 4;i += 4)
3503 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3504 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3505 Mem_Free(fogpixels);
3509 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3510 //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]);
3515 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3519 skinframe_t *skinframe;
3521 if (cls.state == ca_dedicated)
3524 // if already loaded just return it, otherwise make a new skinframe
3525 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3526 if (skinframe && skinframe->base)
3529 skinframe->stain = NULL;
3530 skinframe->merged = NULL;
3531 skinframe->base = NULL;
3532 skinframe->pants = NULL;
3533 skinframe->shirt = NULL;
3534 skinframe->nmap = NULL;
3535 skinframe->gloss = NULL;
3536 skinframe->glow = NULL;
3537 skinframe->fog = NULL;
3538 skinframe->reflect = NULL;
3539 skinframe->hasalpha = false;
3541 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3545 if (developer_loading.integer)
3546 Con_Printf("loading quake skin \"%s\"\n", name);
3548 // 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)
3549 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3550 memcpy(skinframe->qpixels, skindata, width*height);
3551 skinframe->qwidth = width;
3552 skinframe->qheight = height;
3555 for (i = 0;i < width * height;i++)
3556 featuresmask |= palette_featureflags[skindata[i]];
3558 skinframe->hasalpha = false;
3559 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3560 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3561 skinframe->qgeneratemerged = true;
3562 skinframe->qgeneratebase = skinframe->qhascolormapping;
3563 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3565 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3566 //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]);
3571 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3575 unsigned char *skindata;
3577 if (!skinframe->qpixels)
3580 if (!skinframe->qhascolormapping)
3581 colormapped = false;
3585 if (!skinframe->qgeneratebase)
3590 if (!skinframe->qgeneratemerged)
3594 width = skinframe->qwidth;
3595 height = skinframe->qheight;
3596 skindata = skinframe->qpixels;
3598 if (skinframe->qgeneratenmap)
3600 unsigned char *temp1, *temp2;
3601 skinframe->qgeneratenmap = false;
3602 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3603 temp2 = temp1 + width * height * 4;
3604 // use either a custom palette or the quake palette
3605 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3606 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3607 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);
3611 if (skinframe->qgenerateglow)
3613 skinframe->qgenerateglow = false;
3614 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
3619 skinframe->qgeneratebase = false;
3620 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);
3621 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);
3622 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);
3626 skinframe->qgeneratemerged = false;
3627 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);
3630 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3632 Mem_Free(skinframe->qpixels);
3633 skinframe->qpixels = NULL;
3637 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)
3640 skinframe_t *skinframe;
3642 if (cls.state == ca_dedicated)
3645 // if already loaded just return it, otherwise make a new skinframe
3646 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3647 if (skinframe && skinframe->base)
3650 skinframe->stain = NULL;
3651 skinframe->merged = NULL;
3652 skinframe->base = NULL;
3653 skinframe->pants = NULL;
3654 skinframe->shirt = NULL;
3655 skinframe->nmap = NULL;
3656 skinframe->gloss = NULL;
3657 skinframe->glow = NULL;
3658 skinframe->fog = NULL;
3659 skinframe->reflect = NULL;
3660 skinframe->hasalpha = false;
3662 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3666 if (developer_loading.integer)
3667 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3669 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3670 if (textureflags & TEXF_ALPHA)
3672 for (i = 0;i < width * height;i++)
3674 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3676 skinframe->hasalpha = true;
3680 if (r_loadfog && skinframe->hasalpha)
3681 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3684 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3685 //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]);
3690 skinframe_t *R_SkinFrame_LoadMissing(void)
3692 skinframe_t *skinframe;
3694 if (cls.state == ca_dedicated)
3697 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3698 skinframe->stain = NULL;
3699 skinframe->merged = NULL;
3700 skinframe->base = NULL;
3701 skinframe->pants = NULL;
3702 skinframe->shirt = NULL;
3703 skinframe->nmap = NULL;
3704 skinframe->gloss = NULL;
3705 skinframe->glow = NULL;
3706 skinframe->fog = NULL;
3707 skinframe->reflect = NULL;
3708 skinframe->hasalpha = false;
3710 skinframe->avgcolor[0] = rand() / RAND_MAX;
3711 skinframe->avgcolor[1] = rand() / RAND_MAX;
3712 skinframe->avgcolor[2] = rand() / RAND_MAX;
3713 skinframe->avgcolor[3] = 1;
3718 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3719 typedef struct suffixinfo_s
3722 qboolean flipx, flipy, flipdiagonal;
3725 static suffixinfo_t suffix[3][6] =
3728 {"px", false, false, false},
3729 {"nx", false, false, false},
3730 {"py", false, false, false},
3731 {"ny", false, false, false},
3732 {"pz", false, false, false},
3733 {"nz", false, false, false}
3736 {"posx", false, false, false},
3737 {"negx", false, false, false},
3738 {"posy", false, false, false},
3739 {"negy", false, false, false},
3740 {"posz", false, false, false},
3741 {"negz", false, false, false}
3744 {"rt", true, false, true},
3745 {"lf", false, true, true},
3746 {"ft", true, true, false},
3747 {"bk", false, false, false},
3748 {"up", true, false, true},
3749 {"dn", true, false, true}
3753 static int componentorder[4] = {0, 1, 2, 3};
3755 rtexture_t *R_LoadCubemap(const char *basename)
3757 int i, j, cubemapsize;
3758 unsigned char *cubemappixels, *image_buffer;
3759 rtexture_t *cubemaptexture;
3761 // must start 0 so the first loadimagepixels has no requested width/height
3763 cubemappixels = NULL;
3764 cubemaptexture = NULL;
3765 // keep trying different suffix groups (posx, px, rt) until one loads
3766 for (j = 0;j < 3 && !cubemappixels;j++)
3768 // load the 6 images in the suffix group
3769 for (i = 0;i < 6;i++)
3771 // generate an image name based on the base and and suffix
3772 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3774 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3776 // an image loaded, make sure width and height are equal
3777 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3779 // if this is the first image to load successfully, allocate the cubemap memory
3780 if (!cubemappixels && image_width >= 1)
3782 cubemapsize = image_width;
3783 // note this clears to black, so unavailable sides are black
3784 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3786 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3788 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);
3791 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3793 Mem_Free(image_buffer);
3797 // if a cubemap loaded, upload it
3800 if (developer_loading.integer)
3801 Con_Printf("loading cubemap \"%s\"\n", basename);
3803 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);
3804 Mem_Free(cubemappixels);
3808 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3809 if (developer_loading.integer)
3811 Con_Printf("(tried tried images ");
3812 for (j = 0;j < 3;j++)
3813 for (i = 0;i < 6;i++)
3814 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3815 Con_Print(" and was unable to find any of them).\n");
3818 return cubemaptexture;
3821 rtexture_t *R_GetCubemap(const char *basename)
3824 for (i = 0;i < r_texture_numcubemaps;i++)
3825 if (r_texture_cubemaps[i] != NULL)
3826 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3827 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3828 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3829 return r_texture_whitecube;
3830 r_texture_numcubemaps++;
3831 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3832 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3833 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3834 return r_texture_cubemaps[i]->texture;
3837 void R_FreeCubemap(const char *basename)
3841 for (i = 0;i < r_texture_numcubemaps;i++)
3843 if (r_texture_cubemaps[i] != NULL)
3845 if (r_texture_cubemaps[i]->texture)
3847 if (developer_loading.integer)
3848 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3849 R_FreeTexture(r_texture_cubemaps[i]->texture);
3850 Mem_Free(r_texture_cubemaps[i]);
3851 r_texture_cubemaps[i] = NULL;
3857 void R_FreeCubemaps(void)
3860 for (i = 0;i < r_texture_numcubemaps;i++)
3862 if (developer_loading.integer)
3863 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3864 if (r_texture_cubemaps[i] != NULL)
3866 if (r_texture_cubemaps[i]->texture)
3867 R_FreeTexture(r_texture_cubemaps[i]->texture);
3868 Mem_Free(r_texture_cubemaps[i]);
3871 r_texture_numcubemaps = 0;
3874 void R_Main_FreeViewCache(void)
3876 if (r_refdef.viewcache.entityvisible)
3877 Mem_Free(r_refdef.viewcache.entityvisible);
3878 if (r_refdef.viewcache.world_pvsbits)
3879 Mem_Free(r_refdef.viewcache.world_pvsbits);
3880 if (r_refdef.viewcache.world_leafvisible)
3881 Mem_Free(r_refdef.viewcache.world_leafvisible);
3882 if (r_refdef.viewcache.world_surfacevisible)
3883 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3884 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3887 void R_Main_ResizeViewCache(void)
3889 int numentities = r_refdef.scene.numentities;
3890 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3891 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3892 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3893 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3894 if (r_refdef.viewcache.maxentities < numentities)
3896 r_refdef.viewcache.maxentities = numentities;
3897 if (r_refdef.viewcache.entityvisible)
3898 Mem_Free(r_refdef.viewcache.entityvisible);
3899 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3901 if (r_refdef.viewcache.world_numclusters != numclusters)
3903 r_refdef.viewcache.world_numclusters = numclusters;
3904 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3905 if (r_refdef.viewcache.world_pvsbits)
3906 Mem_Free(r_refdef.viewcache.world_pvsbits);
3907 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3909 if (r_refdef.viewcache.world_numleafs != numleafs)
3911 r_refdef.viewcache.world_numleafs = numleafs;
3912 if (r_refdef.viewcache.world_leafvisible)
3913 Mem_Free(r_refdef.viewcache.world_leafvisible);
3914 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3916 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3918 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3919 if (r_refdef.viewcache.world_surfacevisible)
3920 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3921 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3925 extern rtexture_t *loadingscreentexture;
3926 void gl_main_start(void)
3928 loadingscreentexture = NULL;
3929 r_texture_blanknormalmap = NULL;
3930 r_texture_white = NULL;
3931 r_texture_grey128 = NULL;
3932 r_texture_black = NULL;
3933 r_texture_whitecube = NULL;
3934 r_texture_normalizationcube = NULL;
3935 r_texture_fogattenuation = NULL;
3936 r_texture_fogheighttexture = NULL;
3937 r_texture_gammaramps = NULL;
3938 r_texture_numcubemaps = 0;
3940 r_loaddds = r_texture_dds_load.integer != 0;
3941 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3943 switch(vid.renderpath)
3945 case RENDERPATH_GL20:
3946 case RENDERPATH_D3D9:
3947 case RENDERPATH_D3D10:
3948 case RENDERPATH_D3D11:
3949 case RENDERPATH_SOFT:
3950 case RENDERPATH_GLES2:
3951 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3952 Cvar_SetValueQuick(&gl_combine, 1);
3953 Cvar_SetValueQuick(&r_glsl, 1);
3954 r_loadnormalmap = true;
3958 case RENDERPATH_GL13:
3959 case RENDERPATH_GLES1:
3960 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3961 Cvar_SetValueQuick(&gl_combine, 1);
3962 Cvar_SetValueQuick(&r_glsl, 0);
3963 r_loadnormalmap = false;
3964 r_loadgloss = false;
3967 case RENDERPATH_GL11:
3968 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3969 Cvar_SetValueQuick(&gl_combine, 0);
3970 Cvar_SetValueQuick(&r_glsl, 0);
3971 r_loadnormalmap = false;
3972 r_loadgloss = false;
3978 R_FrameData_Reset();
3982 memset(r_queries, 0, sizeof(r_queries));
3984 r_qwskincache = NULL;
3985 r_qwskincache_size = 0;
3987 // due to caching of texture_t references, the collision cache must be reset
3988 Collision_Cache_Reset(true);
3990 // set up r_skinframe loading system for textures
3991 memset(&r_skinframe, 0, sizeof(r_skinframe));
3992 r_skinframe.loadsequence = 1;
3993 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3995 r_main_texturepool = R_AllocTexturePool();
3996 R_BuildBlankTextures();
3998 if (vid.support.arb_texture_cube_map)
4001 R_BuildNormalizationCube();
4003 r_texture_fogattenuation = NULL;
4004 r_texture_fogheighttexture = NULL;
4005 r_texture_gammaramps = NULL;
4006 //r_texture_fogintensity = NULL;
4007 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4008 memset(&r_waterstate, 0, sizeof(r_waterstate));
4009 r_glsl_permutation = NULL;
4010 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4011 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4012 glslshaderstring = NULL;
4014 r_hlsl_permutation = NULL;
4015 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4016 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4018 hlslshaderstring = NULL;
4019 memset(&r_svbsp, 0, sizeof (r_svbsp));
4021 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4022 r_texture_numcubemaps = 0;
4024 r_refdef.fogmasktable_density = 0;
4027 void gl_main_shutdown(void)
4030 R_FrameData_Reset();
4032 R_Main_FreeViewCache();
4034 switch(vid.renderpath)
4036 case RENDERPATH_GL11:
4037 case RENDERPATH_GL13:
4038 case RENDERPATH_GL20:
4039 case RENDERPATH_GLES1:
4040 case RENDERPATH_GLES2:
4042 qglDeleteQueriesARB(r_maxqueries, r_queries);
4044 case RENDERPATH_D3D9:
4045 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4047 case RENDERPATH_D3D10:
4048 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4050 case RENDERPATH_D3D11:
4051 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4053 case RENDERPATH_SOFT:
4059 memset(r_queries, 0, sizeof(r_queries));
4061 r_qwskincache = NULL;
4062 r_qwskincache_size = 0;
4064 // clear out the r_skinframe state
4065 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4066 memset(&r_skinframe, 0, sizeof(r_skinframe));
4069 Mem_Free(r_svbsp.nodes);
4070 memset(&r_svbsp, 0, sizeof (r_svbsp));
4071 R_FreeTexturePool(&r_main_texturepool);
4072 loadingscreentexture = NULL;
4073 r_texture_blanknormalmap = NULL;
4074 r_texture_white = NULL;
4075 r_texture_grey128 = NULL;
4076 r_texture_black = NULL;
4077 r_texture_whitecube = NULL;
4078 r_texture_normalizationcube = NULL;
4079 r_texture_fogattenuation = NULL;
4080 r_texture_fogheighttexture = NULL;
4081 r_texture_gammaramps = NULL;
4082 r_texture_numcubemaps = 0;
4083 //r_texture_fogintensity = NULL;
4084 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4085 memset(&r_waterstate, 0, sizeof(r_waterstate));
4088 r_glsl_permutation = NULL;
4089 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4090 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4091 glslshaderstring = NULL;
4093 r_hlsl_permutation = NULL;
4094 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4095 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4097 hlslshaderstring = NULL;
4100 extern void CL_ParseEntityLump(char *entitystring);
4101 void gl_main_newmap(void)
4103 // FIXME: move this code to client
4104 char *entities, entname[MAX_QPATH];
4106 Mem_Free(r_qwskincache);
4107 r_qwskincache = NULL;
4108 r_qwskincache_size = 0;
4111 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4112 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4114 CL_ParseEntityLump(entities);
4118 if (cl.worldmodel->brush.entities)
4119 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4121 R_Main_FreeViewCache();
4123 R_FrameData_Reset();
4126 void GL_Main_Init(void)
4128 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4130 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4131 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4132 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4133 if (gamemode == GAME_NEHAHRA)
4135 Cvar_RegisterVariable (&gl_fogenable);
4136 Cvar_RegisterVariable (&gl_fogdensity);
4137 Cvar_RegisterVariable (&gl_fogred);
4138 Cvar_RegisterVariable (&gl_foggreen);
4139 Cvar_RegisterVariable (&gl_fogblue);
4140 Cvar_RegisterVariable (&gl_fogstart);
4141 Cvar_RegisterVariable (&gl_fogend);
4142 Cvar_RegisterVariable (&gl_skyclip);
4144 Cvar_RegisterVariable(&r_motionblur);
4145 Cvar_RegisterVariable(&r_damageblur);
4146 Cvar_RegisterVariable(&r_motionblur_averaging);
4147 Cvar_RegisterVariable(&r_motionblur_randomize);
4148 Cvar_RegisterVariable(&r_motionblur_minblur);
4149 Cvar_RegisterVariable(&r_motionblur_maxblur);
4150 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4151 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4152 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4153 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4154 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4155 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4156 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4157 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4158 Cvar_RegisterVariable(&r_equalize_entities_by);
4159 Cvar_RegisterVariable(&r_equalize_entities_to);
4160 Cvar_RegisterVariable(&r_depthfirst);
4161 Cvar_RegisterVariable(&r_useinfinitefarclip);
4162 Cvar_RegisterVariable(&r_farclip_base);
4163 Cvar_RegisterVariable(&r_farclip_world);
4164 Cvar_RegisterVariable(&r_nearclip);
4165 Cvar_RegisterVariable(&r_deformvertexes);
4166 Cvar_RegisterVariable(&r_transparent);
4167 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4168 Cvar_RegisterVariable(&r_showoverdraw);
4169 Cvar_RegisterVariable(&r_showbboxes);
4170 Cvar_RegisterVariable(&r_showsurfaces);
4171 Cvar_RegisterVariable(&r_showtris);
4172 Cvar_RegisterVariable(&r_shownormals);
4173 Cvar_RegisterVariable(&r_showlighting);
4174 Cvar_RegisterVariable(&r_showshadowvolumes);
4175 Cvar_RegisterVariable(&r_showcollisionbrushes);
4176 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4177 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4178 Cvar_RegisterVariable(&r_showdisabledepthtest);
4179 Cvar_RegisterVariable(&r_drawportals);
4180 Cvar_RegisterVariable(&r_drawentities);
4181 Cvar_RegisterVariable(&r_draw2d);
4182 Cvar_RegisterVariable(&r_drawworld);
4183 Cvar_RegisterVariable(&r_cullentities_trace);
4184 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4185 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4186 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4187 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4188 Cvar_RegisterVariable(&r_drawviewmodel);
4189 Cvar_RegisterVariable(&r_drawexteriormodel);
4190 Cvar_RegisterVariable(&r_speeds);
4191 Cvar_RegisterVariable(&r_fullbrights);
4192 Cvar_RegisterVariable(&r_wateralpha);
4193 Cvar_RegisterVariable(&r_dynamic);
4194 Cvar_RegisterVariable(&r_fakelight);
4195 Cvar_RegisterVariable(&r_fakelight_intensity);
4196 Cvar_RegisterVariable(&r_fullbright);
4197 Cvar_RegisterVariable(&r_shadows);
4198 Cvar_RegisterVariable(&r_shadows_darken);
4199 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4200 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4201 Cvar_RegisterVariable(&r_shadows_throwdistance);
4202 Cvar_RegisterVariable(&r_shadows_throwdirection);
4203 Cvar_RegisterVariable(&r_shadows_focus);
4204 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4205 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4206 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4207 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4208 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4209 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4210 Cvar_RegisterVariable(&r_fog_exp2);
4211 Cvar_RegisterVariable(&r_fog_clear);
4212 Cvar_RegisterVariable(&r_drawfog);
4213 Cvar_RegisterVariable(&r_transparentdepthmasking);
4214 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4215 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4216 Cvar_RegisterVariable(&r_texture_dds_load);
4217 Cvar_RegisterVariable(&r_texture_dds_save);
4218 Cvar_RegisterVariable(&r_textureunits);
4219 Cvar_RegisterVariable(&gl_combine);
4220 Cvar_RegisterVariable(&r_viewfbo);
4221 Cvar_RegisterVariable(&r_viewscale);
4222 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4223 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4224 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4225 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4226 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4227 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4228 Cvar_RegisterVariable(&r_glsl);
4229 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4230 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4231 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4232 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4233 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4234 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4235 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4236 Cvar_RegisterVariable(&r_glsl_postprocess);
4237 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4238 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4239 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4240 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4241 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4242 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4243 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4244 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4246 Cvar_RegisterVariable(&r_water);
4247 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4248 Cvar_RegisterVariable(&r_water_clippingplanebias);
4249 Cvar_RegisterVariable(&r_water_refractdistort);
4250 Cvar_RegisterVariable(&r_water_reflectdistort);
4251 Cvar_RegisterVariable(&r_water_scissormode);
4252 Cvar_RegisterVariable(&r_water_lowquality);
4254 Cvar_RegisterVariable(&r_lerpsprites);
4255 Cvar_RegisterVariable(&r_lerpmodels);
4256 Cvar_RegisterVariable(&r_lerplightstyles);
4257 Cvar_RegisterVariable(&r_waterscroll);
4258 Cvar_RegisterVariable(&r_bloom);
4259 Cvar_RegisterVariable(&r_bloom_colorscale);
4260 Cvar_RegisterVariable(&r_bloom_brighten);
4261 Cvar_RegisterVariable(&r_bloom_blur);
4262 Cvar_RegisterVariable(&r_bloom_resolution);
4263 Cvar_RegisterVariable(&r_bloom_colorexponent);
4264 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4265 Cvar_RegisterVariable(&r_hdr);
4266 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4267 Cvar_RegisterVariable(&r_hdr_glowintensity);
4268 Cvar_RegisterVariable(&r_hdr_range);
4269 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4270 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4271 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4272 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4273 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4274 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4275 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4276 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4277 Cvar_RegisterVariable(&developer_texturelogging);
4278 Cvar_RegisterVariable(&gl_lightmaps);
4279 Cvar_RegisterVariable(&r_test);
4280 Cvar_RegisterVariable(&r_glsl_saturation);
4281 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4282 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4283 Cvar_RegisterVariable(&r_framedatasize);
4284 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4285 Cvar_SetValue("r_fullbrights", 0);
4286 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4289 extern void R_Textures_Init(void);
4290 extern void GL_Draw_Init(void);
4291 extern void GL_Main_Init(void);
4292 extern void R_Shadow_Init(void);
4293 extern void R_Sky_Init(void);
4294 extern void GL_Surf_Init(void);
4295 extern void R_Particles_Init(void);
4296 extern void R_Explosion_Init(void);
4297 extern void gl_backend_init(void);
4298 extern void Sbar_Init(void);
4299 extern void R_LightningBeams_Init(void);
4300 extern void Mod_RenderInit(void);
4301 extern void Font_Init(void);
4303 void Render_Init(void)
4316 R_LightningBeams_Init();
4325 extern char *ENGINE_EXTENSIONS;
4328 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4329 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4330 gl_version = (const char *)qglGetString(GL_VERSION);
4331 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4335 if (!gl_platformextensions)
4336 gl_platformextensions = "";
4338 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4339 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4340 Con_Printf("GL_VERSION: %s\n", gl_version);
4341 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4342 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4344 VID_CheckExtensions();
4346 // LordHavoc: report supported extensions
4347 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4349 // clear to black (loading plaque will be seen over this)
4350 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4353 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4357 if (r_trippy.integer)
4359 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4361 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4364 p = r_refdef.view.frustum + i;
4369 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4373 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4377 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4381 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4385 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4389 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4393 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4397 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4405 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4409 if (r_trippy.integer)
4411 for (i = 0;i < numplanes;i++)
4418 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4422 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4426 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4430 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4434 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4438 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4442 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4446 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4454 //==================================================================================
4456 // LordHavoc: this stores temporary data used within the same frame
4458 typedef struct r_framedata_mem_s
4460 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4461 size_t size; // how much usable space
4462 size_t current; // how much space in use
4463 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4464 size_t wantedsize; // how much space was allocated
4465 unsigned char *data; // start of real data (16byte aligned)
4469 static r_framedata_mem_t *r_framedata_mem;
4471 void R_FrameData_Reset(void)
4473 while (r_framedata_mem)
4475 r_framedata_mem_t *next = r_framedata_mem->purge;
4476 Mem_Free(r_framedata_mem);
4477 r_framedata_mem = next;
4481 void R_FrameData_Resize(void)
4484 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4485 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4486 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4488 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4489 newmem->wantedsize = wantedsize;
4490 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4491 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4492 newmem->current = 0;
4494 newmem->purge = r_framedata_mem;
4495 r_framedata_mem = newmem;
4499 void R_FrameData_NewFrame(void)
4501 R_FrameData_Resize();
4502 if (!r_framedata_mem)
4504 // if we ran out of space on the last frame, free the old memory now
4505 while (r_framedata_mem->purge)
4507 // repeatedly remove the second item in the list, leaving only head
4508 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4509 Mem_Free(r_framedata_mem->purge);
4510 r_framedata_mem->purge = next;
4512 // reset the current mem pointer
4513 r_framedata_mem->current = 0;
4514 r_framedata_mem->mark = 0;
4517 void *R_FrameData_Alloc(size_t size)
4521 // align to 16 byte boundary - the data pointer is already aligned, so we
4522 // only need to ensure the size of every allocation is also aligned
4523 size = (size + 15) & ~15;
4525 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4527 // emergency - we ran out of space, allocate more memory
4528 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4529 R_FrameData_Resize();
4532 data = r_framedata_mem->data + r_framedata_mem->current;
4533 r_framedata_mem->current += size;
4535 // count the usage for stats
4536 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4537 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4539 return (void *)data;
4542 void *R_FrameData_Store(size_t size, void *data)
4544 void *d = R_FrameData_Alloc(size);
4546 memcpy(d, data, size);
4550 void R_FrameData_SetMark(void)
4552 if (!r_framedata_mem)
4554 r_framedata_mem->mark = r_framedata_mem->current;
4557 void R_FrameData_ReturnToMark(void)
4559 if (!r_framedata_mem)
4561 r_framedata_mem->current = r_framedata_mem->mark;
4564 //==================================================================================
4566 // LordHavoc: animcache originally written by Echon, rewritten since then
4569 * Animation cache prevents re-generating mesh data for an animated model
4570 * multiple times in one frame for lighting, shadowing, reflections, etc.
4573 void R_AnimCache_Free(void)
4577 void R_AnimCache_ClearCache(void)
4580 entity_render_t *ent;
4582 for (i = 0;i < r_refdef.scene.numentities;i++)
4584 ent = r_refdef.scene.entities[i];
4585 ent->animcache_vertex3f = NULL;
4586 ent->animcache_normal3f = NULL;
4587 ent->animcache_svector3f = NULL;
4588 ent->animcache_tvector3f = NULL;
4589 ent->animcache_vertexmesh = NULL;
4590 ent->animcache_vertex3fbuffer = NULL;
4591 ent->animcache_vertexmeshbuffer = NULL;
4595 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4599 // check if we need the meshbuffers
4600 if (!vid.useinterleavedarrays)
4603 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4604 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4605 // TODO: upload vertex3f buffer?
4606 if (ent->animcache_vertexmesh)
4608 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4609 for (i = 0;i < numvertices;i++)
4610 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4611 if (ent->animcache_svector3f)
4612 for (i = 0;i < numvertices;i++)
4613 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4614 if (ent->animcache_tvector3f)
4615 for (i = 0;i < numvertices;i++)
4616 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4617 if (ent->animcache_normal3f)
4618 for (i = 0;i < numvertices;i++)
4619 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4620 // TODO: upload vertexmeshbuffer?
4624 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4626 dp_model_t *model = ent->model;
4628 // see if it's already cached this frame
4629 if (ent->animcache_vertex3f)
4631 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4632 if (wantnormals || wanttangents)
4634 if (ent->animcache_normal3f)
4635 wantnormals = false;
4636 if (ent->animcache_svector3f)
4637 wanttangents = false;
4638 if (wantnormals || wanttangents)
4640 numvertices = model->surfmesh.num_vertices;
4642 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4645 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4646 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4648 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4649 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4655 // see if this ent is worth caching
4656 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4658 // get some memory for this entity and generate mesh data
4659 numvertices = model->surfmesh.num_vertices;
4660 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4662 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4665 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4666 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4668 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4669 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4674 void R_AnimCache_CacheVisibleEntities(void)
4677 qboolean wantnormals = true;
4678 qboolean wanttangents = !r_showsurfaces.integer;
4680 switch(vid.renderpath)
4682 case RENDERPATH_GL20:
4683 case RENDERPATH_D3D9:
4684 case RENDERPATH_D3D10:
4685 case RENDERPATH_D3D11:
4686 case RENDERPATH_GLES2:
4688 case RENDERPATH_GL11:
4689 case RENDERPATH_GL13:
4690 case RENDERPATH_GLES1:
4691 wanttangents = false;
4693 case RENDERPATH_SOFT:
4697 if (r_shownormals.integer)
4698 wanttangents = wantnormals = true;
4700 // TODO: thread this
4701 // NOTE: R_PrepareRTLights() also caches entities
4703 for (i = 0;i < r_refdef.scene.numentities;i++)
4704 if (r_refdef.viewcache.entityvisible[i])
4705 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4708 //==================================================================================
4710 extern cvar_t r_overheadsprites_pushback;
4712 static void R_View_UpdateEntityLighting (void)
4715 entity_render_t *ent;
4716 vec3_t tempdiffusenormal, avg;
4717 vec_t f, fa, fd, fdd;
4718 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4720 for (i = 0;i < r_refdef.scene.numentities;i++)
4722 ent = r_refdef.scene.entities[i];
4724 // skip unseen models
4725 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4729 if (ent->model && ent->model->brush.num_leafs)
4731 // TODO: use modellight for r_ambient settings on world?
4732 VectorSet(ent->modellight_ambient, 0, 0, 0);
4733 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4734 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4738 // fetch the lighting from the worldmodel data
4739 VectorClear(ent->modellight_ambient);
4740 VectorClear(ent->modellight_diffuse);
4741 VectorClear(tempdiffusenormal);
4742 if (ent->flags & RENDER_LIGHT)
4745 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4747 // complete lightning for lit sprites
4748 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4749 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4751 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4752 org[2] = org[2] + r_overheadsprites_pushback.value;
4753 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4756 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4758 if(ent->flags & RENDER_EQUALIZE)
4760 // first fix up ambient lighting...
4761 if(r_equalize_entities_minambient.value > 0)
4763 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4766 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4767 if(fa < r_equalize_entities_minambient.value * fd)
4770 // fa'/fd' = minambient
4771 // fa'+0.25*fd' = fa+0.25*fd
4773 // fa' = fd' * minambient
4774 // fd'*(0.25+minambient) = fa+0.25*fd
4776 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4777 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4779 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4780 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
4781 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4782 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4787 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4789 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4790 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4794 // adjust brightness and saturation to target
4795 avg[0] = avg[1] = avg[2] = fa / f;
4796 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4797 avg[0] = avg[1] = avg[2] = fd / f;
4798 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4804 VectorSet(ent->modellight_ambient, 1, 1, 1);
4806 // move the light direction into modelspace coordinates for lighting code
4807 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4808 if(VectorLength2(ent->modellight_lightdir) == 0)
4809 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4810 VectorNormalize(ent->modellight_lightdir);
4814 #define MAX_LINEOFSIGHTTRACES 64
4816 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4819 vec3_t boxmins, boxmaxs;
4822 dp_model_t *model = r_refdef.scene.worldmodel;
4824 if (!model || !model->brush.TraceLineOfSight)
4827 // expand the box a little
4828 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4829 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4830 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4831 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4832 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4833 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4835 // return true if eye is inside enlarged box
4836 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4840 VectorCopy(eye, start);
4841 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4842 if (model->brush.TraceLineOfSight(model, start, end))
4845 // try various random positions
4846 for (i = 0;i < numsamples;i++)
4848 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4849 if (model->brush.TraceLineOfSight(model, start, end))
4857 static void R_View_UpdateEntityVisible (void)
4862 entity_render_t *ent;
4864 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4865 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4866 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4867 : RENDER_EXTERIORMODEL;
4868 if (!r_drawviewmodel.integer)
4869 renderimask |= RENDER_VIEWMODEL;
4870 if (!r_drawexteriormodel.integer)
4871 renderimask |= RENDER_EXTERIORMODEL;
4872 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4874 // worldmodel can check visibility
4875 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4876 for (i = 0;i < r_refdef.scene.numentities;i++)
4878 ent = r_refdef.scene.entities[i];
4879 if (!(ent->flags & renderimask))
4880 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)))
4881 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))
4882 r_refdef.viewcache.entityvisible[i] = true;
4887 // no worldmodel or it can't check visibility
4888 for (i = 0;i < r_refdef.scene.numentities;i++)
4890 ent = r_refdef.scene.entities[i];
4891 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));
4894 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4895 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4897 for (i = 0;i < r_refdef.scene.numentities;i++)
4899 if (!r_refdef.viewcache.entityvisible[i])
4901 ent = r_refdef.scene.entities[i];
4902 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4904 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4906 continue; // temp entities do pvs only
4907 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4908 ent->last_trace_visibility = realtime;
4909 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4910 r_refdef.viewcache.entityvisible[i] = 0;
4916 /// only used if skyrendermasked, and normally returns false
4917 int R_DrawBrushModelsSky (void)
4920 entity_render_t *ent;
4923 for (i = 0;i < r_refdef.scene.numentities;i++)
4925 if (!r_refdef.viewcache.entityvisible[i])
4927 ent = r_refdef.scene.entities[i];
4928 if (!ent->model || !ent->model->DrawSky)
4930 ent->model->DrawSky(ent);
4936 static void R_DrawNoModel(entity_render_t *ent);
4937 static void R_DrawModels(void)
4940 entity_render_t *ent;
4942 for (i = 0;i < r_refdef.scene.numentities;i++)
4944 if (!r_refdef.viewcache.entityvisible[i])
4946 ent = r_refdef.scene.entities[i];
4947 r_refdef.stats.entities++;
4949 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4952 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4953 Con_Printf("R_DrawModels\n");
4954 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]);
4955 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);
4956 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);
4959 if (ent->model && ent->model->Draw != NULL)
4960 ent->model->Draw(ent);
4966 static void R_DrawModelsDepth(void)
4969 entity_render_t *ent;
4971 for (i = 0;i < r_refdef.scene.numentities;i++)
4973 if (!r_refdef.viewcache.entityvisible[i])
4975 ent = r_refdef.scene.entities[i];
4976 if (ent->model && ent->model->DrawDepth != NULL)
4977 ent->model->DrawDepth(ent);
4981 static void R_DrawModelsDebug(void)
4984 entity_render_t *ent;
4986 for (i = 0;i < r_refdef.scene.numentities;i++)
4988 if (!r_refdef.viewcache.entityvisible[i])
4990 ent = r_refdef.scene.entities[i];
4991 if (ent->model && ent->model->DrawDebug != NULL)
4992 ent->model->DrawDebug(ent);
4996 static void R_DrawModelsAddWaterPlanes(void)
4999 entity_render_t *ent;
5001 for (i = 0;i < r_refdef.scene.numentities;i++)
5003 if (!r_refdef.viewcache.entityvisible[i])
5005 ent = r_refdef.scene.entities[i];
5006 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5007 ent->model->DrawAddWaterPlanes(ent);
5011 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5013 if (r_hdr_irisadaptation.integer)
5017 vec3_t diffusenormal;
5021 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5022 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5023 brightness = max(0.0000001f, brightness);
5024 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5025 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5026 current = r_hdr_irisadaptation_value.value;
5028 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5029 else if (current > goal)
5030 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5031 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5032 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5034 else if (r_hdr_irisadaptation_value.value != 1.0f)
5035 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5038 static void R_View_SetFrustum(const int *scissor)
5041 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5042 vec3_t forward, left, up, origin, v;
5046 // flipped x coordinates (because x points left here)
5047 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5048 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5050 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5051 switch(vid.renderpath)
5053 case RENDERPATH_D3D9:
5054 case RENDERPATH_D3D10:
5055 case RENDERPATH_D3D11:
5056 // non-flipped y coordinates
5057 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5058 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5060 case RENDERPATH_SOFT:
5061 case RENDERPATH_GL11:
5062 case RENDERPATH_GL13:
5063 case RENDERPATH_GL20:
5064 case RENDERPATH_GLES1:
5065 case RENDERPATH_GLES2:
5066 // non-flipped y coordinates
5067 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5068 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5073 // we can't trust r_refdef.view.forward and friends in reflected scenes
5074 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5077 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5078 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5079 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5080 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5081 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5082 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5083 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5084 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5085 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5086 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5087 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5088 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5092 zNear = r_refdef.nearclip;
5093 nudge = 1.0 - 1.0 / (1<<23);
5094 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5095 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5096 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5097 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5098 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5099 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5100 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5101 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5107 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5108 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5109 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5110 r_refdef.view.frustum[0].dist = m[15] - m[12];
5112 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5113 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5114 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5115 r_refdef.view.frustum[1].dist = m[15] + m[12];
5117 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5118 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5119 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5120 r_refdef.view.frustum[2].dist = m[15] - m[13];
5122 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5123 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5124 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5125 r_refdef.view.frustum[3].dist = m[15] + m[13];
5127 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5128 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5129 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5130 r_refdef.view.frustum[4].dist = m[15] - m[14];
5132 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5133 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5134 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5135 r_refdef.view.frustum[5].dist = m[15] + m[14];
5138 if (r_refdef.view.useperspective)
5140 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5141 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]);
5142 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]);
5143 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]);
5144 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]);
5146 // then the normals from the corners relative to origin
5147 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5148 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5149 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5150 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5152 // in a NORMAL view, forward cross left == up
5153 // in a REFLECTED view, forward cross left == down
5154 // so our cross products above need to be adjusted for a left handed coordinate system
5155 CrossProduct(forward, left, v);
5156 if(DotProduct(v, up) < 0)
5158 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5159 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5160 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5161 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5164 // Leaving those out was a mistake, those were in the old code, and they
5165 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5166 // I couldn't reproduce it after adding those normalizations. --blub
5167 VectorNormalize(r_refdef.view.frustum[0].normal);
5168 VectorNormalize(r_refdef.view.frustum[1].normal);
5169 VectorNormalize(r_refdef.view.frustum[2].normal);
5170 VectorNormalize(r_refdef.view.frustum[3].normal);
5172 // make the corners absolute
5173 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5174 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5175 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5176 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5179 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5181 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5182 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5183 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5184 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5185 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5189 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5190 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5191 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5192 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5193 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5194 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5195 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5196 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5197 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5198 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5200 r_refdef.view.numfrustumplanes = 5;
5202 if (r_refdef.view.useclipplane)
5204 r_refdef.view.numfrustumplanes = 6;
5205 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5208 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5209 PlaneClassify(r_refdef.view.frustum + i);
5211 // LordHavoc: note to all quake engine coders, Quake had a special case
5212 // for 90 degrees which assumed a square view (wrong), so I removed it,
5213 // Quake2 has it disabled as well.
5215 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5216 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5217 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5218 //PlaneClassify(&frustum[0]);
5220 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5221 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5222 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5223 //PlaneClassify(&frustum[1]);
5225 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5226 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5227 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5228 //PlaneClassify(&frustum[2]);
5230 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5231 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5232 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5233 //PlaneClassify(&frustum[3]);
5236 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5237 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5238 //PlaneClassify(&frustum[4]);
5241 void R_View_UpdateWithScissor(const int *myscissor)
5243 R_Main_ResizeViewCache();
5244 R_View_SetFrustum(myscissor);
5245 R_View_WorldVisibility(r_refdef.view.useclipplane);
5246 R_View_UpdateEntityVisible();
5247 R_View_UpdateEntityLighting();
5250 void R_View_Update(void)
5252 R_Main_ResizeViewCache();
5253 R_View_SetFrustum(NULL);
5254 R_View_WorldVisibility(r_refdef.view.useclipplane);
5255 R_View_UpdateEntityVisible();
5256 R_View_UpdateEntityLighting();
5259 float viewscalefpsadjusted = 1.0f;
5261 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5263 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5264 scale = bound(0.03125f, scale, 1.0f);
5265 *outwidth = (int)ceil(width * scale);
5266 *outheight = (int)ceil(height * scale);
5269 void R_Mesh_SetMainRenderTargets(void)
5271 if (r_bloomstate.fbo_framebuffer)
5272 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5274 R_Mesh_ResetRenderTargets();
5277 void R_SetupView(qboolean allowwaterclippingplane)
5279 const float *customclipplane = NULL;
5281 int scaledwidth, scaledheight;
5282 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5284 // LordHavoc: couldn't figure out how to make this approach the
5285 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5286 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5287 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5288 dist = r_refdef.view.clipplane.dist;
5289 plane[0] = r_refdef.view.clipplane.normal[0];
5290 plane[1] = r_refdef.view.clipplane.normal[1];
5291 plane[2] = r_refdef.view.clipplane.normal[2];
5293 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5296 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5297 if (!r_refdef.view.useperspective)
5298 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);
5299 else if (vid.stencil && r_useinfinitefarclip.integer)
5300 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);
5302 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);
5303 R_Mesh_SetMainRenderTargets();
5304 R_SetViewport(&r_refdef.view.viewport);
5305 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5307 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5308 float screenplane[4];
5309 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5310 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5311 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5312 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5313 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5317 void R_EntityMatrix(const matrix4x4_t *matrix)
5319 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5321 gl_modelmatrixchanged = false;
5322 gl_modelmatrix = *matrix;
5323 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5324 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5325 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5326 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5328 switch(vid.renderpath)
5330 case RENDERPATH_D3D9:
5332 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5333 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5336 case RENDERPATH_D3D10:
5337 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5339 case RENDERPATH_D3D11:
5340 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5342 case RENDERPATH_GL11:
5343 case RENDERPATH_GL13:
5344 case RENDERPATH_GLES1:
5345 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5347 case RENDERPATH_SOFT:
5348 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5349 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5351 case RENDERPATH_GL20:
5352 case RENDERPATH_GLES2:
5353 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5354 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5360 void R_ResetViewRendering2D(void)
5362 r_viewport_t viewport;
5365 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5366 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);
5367 R_Mesh_ResetRenderTargets();
5368 R_SetViewport(&viewport);
5369 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5370 GL_Color(1, 1, 1, 1);
5371 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5372 GL_BlendFunc(GL_ONE, GL_ZERO);
5373 GL_ScissorTest(false);
5374 GL_DepthMask(false);
5375 GL_DepthRange(0, 1);
5376 GL_DepthTest(false);
5377 GL_DepthFunc(GL_LEQUAL);
5378 R_EntityMatrix(&identitymatrix);
5379 R_Mesh_ResetTextureState();
5380 GL_PolygonOffset(0, 0);
5381 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5382 switch(vid.renderpath)
5384 case RENDERPATH_GL11:
5385 case RENDERPATH_GL13:
5386 case RENDERPATH_GL20:
5387 case RENDERPATH_GLES1:
5388 case RENDERPATH_GLES2:
5389 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5391 case RENDERPATH_D3D9:
5392 case RENDERPATH_D3D10:
5393 case RENDERPATH_D3D11:
5394 case RENDERPATH_SOFT:
5397 GL_CullFace(GL_NONE);
5400 void R_ResetViewRendering3D(void)
5405 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5406 GL_Color(1, 1, 1, 1);
5407 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5408 GL_BlendFunc(GL_ONE, GL_ZERO);
5409 GL_ScissorTest(true);
5411 GL_DepthRange(0, 1);
5413 GL_DepthFunc(GL_LEQUAL);
5414 R_EntityMatrix(&identitymatrix);
5415 R_Mesh_ResetTextureState();
5416 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5417 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5418 switch(vid.renderpath)
5420 case RENDERPATH_GL11:
5421 case RENDERPATH_GL13:
5422 case RENDERPATH_GL20:
5423 case RENDERPATH_GLES1:
5424 case RENDERPATH_GLES2:
5425 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5427 case RENDERPATH_D3D9:
5428 case RENDERPATH_D3D10:
5429 case RENDERPATH_D3D11:
5430 case RENDERPATH_SOFT:
5433 GL_CullFace(r_refdef.view.cullface_back);
5438 R_RenderView_UpdateViewVectors
5441 static void R_RenderView_UpdateViewVectors(void)
5443 // break apart the view matrix into vectors for various purposes
5444 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5445 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5446 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5447 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5448 // make an inverted copy of the view matrix for tracking sprites
5449 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5452 void R_RenderScene(void);
5453 void R_RenderWaterPlanes(void);
5455 static void R_Water_StartFrame(void)
5458 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5459 r_waterstate_waterplane_t *p;
5461 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5464 switch(vid.renderpath)
5466 case RENDERPATH_GL20:
5467 case RENDERPATH_D3D9:
5468 case RENDERPATH_D3D10:
5469 case RENDERPATH_D3D11:
5470 case RENDERPATH_SOFT:
5471 case RENDERPATH_GLES2:
5473 case RENDERPATH_GL11:
5474 case RENDERPATH_GL13:
5475 case RENDERPATH_GLES1:
5479 // set waterwidth and waterheight to the water resolution that will be
5480 // used (often less than the screen resolution for faster rendering)
5481 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5483 // calculate desired texture sizes
5484 // can't use water if the card does not support the texture size
5485 if (!r_water.integer || r_showsurfaces.integer)
5486 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5487 else if (vid.support.arb_texture_non_power_of_two)
5489 texturewidth = waterwidth;
5490 textureheight = waterheight;
5491 camerawidth = waterwidth;
5492 cameraheight = waterheight;
5496 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5497 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5498 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5499 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5502 // allocate textures as needed
5503 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5505 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5506 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5508 if (p->texture_refraction)
5509 R_FreeTexture(p->texture_refraction);
5510 p->texture_refraction = NULL;
5511 if (p->texture_reflection)
5512 R_FreeTexture(p->texture_reflection);
5513 p->texture_reflection = NULL;
5514 if (p->texture_camera)
5515 R_FreeTexture(p->texture_camera);
5516 p->texture_camera = NULL;
5518 memset(&r_waterstate, 0, sizeof(r_waterstate));
5519 r_waterstate.texturewidth = texturewidth;
5520 r_waterstate.textureheight = textureheight;
5521 r_waterstate.camerawidth = camerawidth;
5522 r_waterstate.cameraheight = cameraheight;
5525 if (r_waterstate.texturewidth)
5527 int scaledwidth, scaledheight;
5529 r_waterstate.enabled = true;
5531 // when doing a reduced render (HDR) we want to use a smaller area
5532 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5533 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5534 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5536 // set up variables that will be used in shader setup
5537 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5538 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5539 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5540 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5543 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5544 r_waterstate.numwaterplanes = 0;
5547 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5549 int triangleindex, planeindex;
5555 r_waterstate_waterplane_t *p;
5556 texture_t *t = R_GetCurrentTexture(surface->texture);
5558 // just use the first triangle with a valid normal for any decisions
5559 VectorClear(normal);
5560 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5562 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5563 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5564 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5565 TriangleNormal(vert[0], vert[1], vert[2], normal);
5566 if (VectorLength2(normal) >= 0.001)
5570 VectorCopy(normal, plane.normal);
5571 VectorNormalize(plane.normal);
5572 plane.dist = DotProduct(vert[0], plane.normal);
5573 PlaneClassify(&plane);
5574 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5576 // skip backfaces (except if nocullface is set)
5577 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5579 VectorNegate(plane.normal, plane.normal);
5581 PlaneClassify(&plane);
5585 // find a matching plane if there is one
5586 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5587 if(p->camera_entity == t->camera_entity)
5588 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5590 if (planeindex >= r_waterstate.maxwaterplanes)
5591 return; // nothing we can do, out of planes
5593 // if this triangle does not fit any known plane rendered this frame, add one
5594 if (planeindex >= r_waterstate.numwaterplanes)
5596 // store the new plane
5597 r_waterstate.numwaterplanes++;
5599 // clear materialflags and pvs
5600 p->materialflags = 0;
5601 p->pvsvalid = false;
5602 p->camera_entity = t->camera_entity;
5603 VectorCopy(surface->mins, p->mins);
5604 VectorCopy(surface->maxs, p->maxs);
5609 p->mins[0] = min(p->mins[0], surface->mins[0]);
5610 p->mins[1] = min(p->mins[1], surface->mins[1]);
5611 p->mins[2] = min(p->mins[2], surface->mins[2]);
5612 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5613 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5614 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5616 // merge this surface's materialflags into the waterplane
5617 p->materialflags |= t->currentmaterialflags;
5618 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5620 // merge this surface's PVS into the waterplane
5621 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5622 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5623 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5625 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5631 extern cvar_t r_drawparticles;
5632 extern cvar_t r_drawdecals;
5634 static void R_Water_ProcessPlanes(void)
5637 r_refdef_view_t originalview;
5638 r_refdef_view_t myview;
5639 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;
5640 r_waterstate_waterplane_t *p;
5643 originalview = r_refdef.view;
5645 // lowquality hack, temporarily shut down some cvars and restore afterwards
5646 qualityreduction = r_water_lowquality.integer;
5647 if (qualityreduction > 0)
5649 if (qualityreduction >= 1)
5651 old_r_shadows = r_shadows.integer;
5652 old_r_worldrtlight = r_shadow_realtime_world.integer;
5653 old_r_dlight = r_shadow_realtime_dlight.integer;
5654 Cvar_SetValueQuick(&r_shadows, 0);
5655 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5656 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5658 if (qualityreduction >= 2)
5660 old_r_dynamic = r_dynamic.integer;
5661 old_r_particles = r_drawparticles.integer;
5662 old_r_decals = r_drawdecals.integer;
5663 Cvar_SetValueQuick(&r_dynamic, 0);
5664 Cvar_SetValueQuick(&r_drawparticles, 0);
5665 Cvar_SetValueQuick(&r_drawdecals, 0);
5669 // make sure enough textures are allocated
5670 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5672 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5674 if (!p->texture_refraction)
5675 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);
5676 if (!p->texture_refraction)
5679 else if (p->materialflags & MATERIALFLAG_CAMERA)
5681 if (!p->texture_camera)
5682 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);
5683 if (!p->texture_camera)
5687 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5689 if (!p->texture_reflection)
5690 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);
5691 if (!p->texture_reflection)
5697 r_refdef.view = originalview;
5698 r_refdef.view.showdebug = false;
5699 r_refdef.view.width = r_waterstate.waterwidth;
5700 r_refdef.view.height = r_waterstate.waterheight;
5701 r_refdef.view.useclipplane = true;
5702 myview = r_refdef.view;
5703 r_waterstate.renderingscene = true;
5704 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5706 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5708 r_refdef.view = myview;
5709 if(r_water_scissormode.integer)
5712 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5713 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5716 // render reflected scene and copy into texture
5717 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5718 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5719 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5720 r_refdef.view.clipplane = p->plane;
5721 // reverse the cullface settings for this render
5722 r_refdef.view.cullface_front = GL_FRONT;
5723 r_refdef.view.cullface_back = GL_BACK;
5724 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5726 r_refdef.view.usecustompvs = true;
5728 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5730 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5733 R_ResetViewRendering3D();
5734 R_ClearScreen(r_refdef.fogenabled);
5735 if(r_water_scissormode.integer & 2)
5736 R_View_UpdateWithScissor(myscissor);
5739 if(r_water_scissormode.integer & 1)
5740 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5743 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);
5746 // render the normal view scene and copy into texture
5747 // (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)
5748 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5750 r_refdef.view = myview;
5751 if(r_water_scissormode.integer)
5754 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5755 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5758 r_waterstate.renderingrefraction = true;
5760 r_refdef.view.clipplane = p->plane;
5761 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5762 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5764 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5766 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5767 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5768 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5769 R_RenderView_UpdateViewVectors();
5770 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5772 r_refdef.view.usecustompvs = true;
5773 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);
5777 PlaneClassify(&r_refdef.view.clipplane);
5779 R_ResetViewRendering3D();
5780 R_ClearScreen(r_refdef.fogenabled);
5781 if(r_water_scissormode.integer & 2)
5782 R_View_UpdateWithScissor(myscissor);
5785 if(r_water_scissormode.integer & 1)
5786 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5789 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);
5790 r_waterstate.renderingrefraction = false;
5792 else if (p->materialflags & MATERIALFLAG_CAMERA)
5794 r_refdef.view = myview;
5796 r_refdef.view.clipplane = p->plane;
5797 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5798 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5800 r_refdef.view.width = r_waterstate.camerawidth;
5801 r_refdef.view.height = r_waterstate.cameraheight;
5802 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5803 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5805 if(p->camera_entity)
5807 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5808 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5811 // note: all of the view is used for displaying... so
5812 // there is no use in scissoring
5814 // reverse the cullface settings for this render
5815 r_refdef.view.cullface_front = GL_FRONT;
5816 r_refdef.view.cullface_back = GL_BACK;
5817 // also reverse the view matrix
5818 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
5819 R_RenderView_UpdateViewVectors();
5820 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5822 r_refdef.view.usecustompvs = true;
5823 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);
5826 // camera needs no clipplane
5827 r_refdef.view.useclipplane = false;
5829 PlaneClassify(&r_refdef.view.clipplane);
5831 R_ResetViewRendering3D();
5832 R_ClearScreen(r_refdef.fogenabled);
5836 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);
5837 r_waterstate.renderingrefraction = false;
5841 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5842 r_waterstate.renderingscene = false;
5843 r_refdef.view = originalview;
5844 R_ResetViewRendering3D();
5845 R_ClearScreen(r_refdef.fogenabled);
5849 r_refdef.view = originalview;
5850 r_waterstate.renderingscene = false;
5851 Cvar_SetValueQuick(&r_water, 0);
5852 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5854 // lowquality hack, restore cvars
5855 if (qualityreduction > 0)
5857 if (qualityreduction >= 1)
5859 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5860 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5861 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5863 if (qualityreduction >= 2)
5865 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5866 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5867 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5872 void R_Bloom_StartFrame(void)
5874 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5875 int viewwidth, viewheight;
5878 if (r_viewscale_fpsscaling.integer)
5880 double actualframetime;
5881 double targetframetime;
5883 actualframetime = r_refdef.lastdrawscreentime;
5884 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5885 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5886 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5887 if (r_viewscale_fpsscaling_stepsize.value > 0)
5888 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5889 viewscalefpsadjusted += adjust;
5890 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5893 viewscalefpsadjusted = 1.0f;
5895 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5897 switch(vid.renderpath)
5899 case RENDERPATH_GL20:
5900 case RENDERPATH_D3D9:
5901 case RENDERPATH_D3D10:
5902 case RENDERPATH_D3D11:
5903 case RENDERPATH_SOFT:
5904 case RENDERPATH_GLES2:
5906 case RENDERPATH_GL11:
5907 case RENDERPATH_GL13:
5908 case RENDERPATH_GLES1:
5912 // set bloomwidth and bloomheight to the bloom resolution that will be
5913 // used (often less than the screen resolution for faster rendering)
5914 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5915 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5916 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5917 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5918 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5920 // calculate desired texture sizes
5921 if (vid.support.arb_texture_non_power_of_two)
5923 screentexturewidth = vid.width;
5924 screentextureheight = vid.height;
5925 bloomtexturewidth = r_bloomstate.bloomwidth;
5926 bloomtextureheight = r_bloomstate.bloomheight;
5930 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5931 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5932 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5933 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5936 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))
5938 Cvar_SetValueQuick(&r_hdr, 0);
5939 Cvar_SetValueQuick(&r_bloom, 0);
5940 Cvar_SetValueQuick(&r_motionblur, 0);
5941 Cvar_SetValueQuick(&r_damageblur, 0);
5944 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)
5945 screentexturewidth = screentextureheight = 0;
5946 if (!r_hdr.integer && !r_bloom.integer)
5947 bloomtexturewidth = bloomtextureheight = 0;
5949 textype = TEXTYPE_COLORBUFFER;
5950 switch (vid.renderpath)
5952 case RENDERPATH_GL20:
5953 case RENDERPATH_GLES2:
5954 if (vid.support.ext_framebuffer_object)
5956 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5957 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5960 case RENDERPATH_GL11:
5961 case RENDERPATH_GL13:
5962 case RENDERPATH_GLES1:
5963 case RENDERPATH_D3D9:
5964 case RENDERPATH_D3D10:
5965 case RENDERPATH_D3D11:
5966 case RENDERPATH_SOFT:
5970 // allocate textures as needed
5971 if (r_bloomstate.screentexturewidth != screentexturewidth
5972 || r_bloomstate.screentextureheight != screentextureheight
5973 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5974 || r_bloomstate.bloomtextureheight != bloomtextureheight
5975 || r_bloomstate.texturetype != textype
5976 || r_bloomstate.viewfbo != r_viewfbo.integer)
5978 if (r_bloomstate.texture_bloom)
5979 R_FreeTexture(r_bloomstate.texture_bloom);
5980 r_bloomstate.texture_bloom = NULL;
5981 if (r_bloomstate.texture_screen)
5982 R_FreeTexture(r_bloomstate.texture_screen);
5983 r_bloomstate.texture_screen = NULL;
5984 if (r_bloomstate.fbo_framebuffer)
5985 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5986 r_bloomstate.fbo_framebuffer = 0;
5987 if (r_bloomstate.texture_framebuffercolor)
5988 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5989 r_bloomstate.texture_framebuffercolor = NULL;
5990 if (r_bloomstate.texture_framebufferdepth)
5991 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5992 r_bloomstate.texture_framebufferdepth = NULL;
5993 r_bloomstate.screentexturewidth = screentexturewidth;
5994 r_bloomstate.screentextureheight = screentextureheight;
5995 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5996 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);
5997 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5999 // FIXME: choose depth bits based on a cvar
6000 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6001 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);
6002 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6003 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6004 // render depth into one texture and normalmap into the other
6008 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6009 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6010 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6011 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6012 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6015 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6016 r_bloomstate.bloomtextureheight = bloomtextureheight;
6017 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6018 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);
6019 r_bloomstate.viewfbo = r_viewfbo.integer;
6020 r_bloomstate.texturetype = textype;
6023 // when doing a reduced render (HDR) we want to use a smaller area
6024 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6025 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6026 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6027 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6028 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6030 // set up a texcoord array for the full resolution screen image
6031 // (we have to keep this around to copy back during final render)
6032 r_bloomstate.screentexcoord2f[0] = 0;
6033 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6034 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6035 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6036 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6037 r_bloomstate.screentexcoord2f[5] = 0;
6038 r_bloomstate.screentexcoord2f[6] = 0;
6039 r_bloomstate.screentexcoord2f[7] = 0;
6041 // set up a texcoord array for the reduced resolution bloom image
6042 // (which will be additive blended over the screen image)
6043 r_bloomstate.bloomtexcoord2f[0] = 0;
6044 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6045 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6046 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6047 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6048 r_bloomstate.bloomtexcoord2f[5] = 0;
6049 r_bloomstate.bloomtexcoord2f[6] = 0;
6050 r_bloomstate.bloomtexcoord2f[7] = 0;
6052 switch(vid.renderpath)
6054 case RENDERPATH_GL11:
6055 case RENDERPATH_GL13:
6056 case RENDERPATH_GL20:
6057 case RENDERPATH_SOFT:
6058 case RENDERPATH_GLES1:
6059 case RENDERPATH_GLES2:
6061 case RENDERPATH_D3D9:
6062 case RENDERPATH_D3D10:
6063 case RENDERPATH_D3D11:
6066 for (i = 0;i < 4;i++)
6068 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6069 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6070 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6071 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6077 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6079 r_bloomstate.enabled = true;
6080 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6083 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);
6085 if (r_bloomstate.fbo_framebuffer)
6086 r_refdef.view.clear = true;
6089 void R_Bloom_CopyBloomTexture(float colorscale)
6091 r_refdef.stats.bloom++;
6093 // scale down screen texture to the bloom texture size
6095 R_Mesh_SetMainRenderTargets();
6096 R_SetViewport(&r_bloomstate.viewport);
6097 GL_BlendFunc(GL_ONE, GL_ZERO);
6098 GL_Color(colorscale, colorscale, colorscale, 1);
6099 // 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...
6100 switch(vid.renderpath)
6102 case RENDERPATH_GL11:
6103 case RENDERPATH_GL13:
6104 case RENDERPATH_GL20:
6105 case RENDERPATH_GLES1:
6106 case RENDERPATH_GLES2:
6107 case RENDERPATH_SOFT:
6108 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6110 case RENDERPATH_D3D9:
6111 case RENDERPATH_D3D10:
6112 case RENDERPATH_D3D11:
6113 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6116 // TODO: do boxfilter scale-down in shader?
6117 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6118 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6119 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6121 // we now have a bloom image in the framebuffer
6122 // copy it into the bloom image texture for later processing
6123 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);
6124 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6127 void R_Bloom_CopyHDRTexture(void)
6129 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);
6130 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6133 void R_Bloom_MakeTexture(void)
6136 float xoffset, yoffset, r, brighten;
6138 r_refdef.stats.bloom++;
6140 R_ResetViewRendering2D();
6142 // we have a bloom image in the framebuffer
6144 R_SetViewport(&r_bloomstate.viewport);
6146 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6149 r = bound(0, r_bloom_colorexponent.value / x, 1);
6150 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6152 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6153 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, 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 // copy the vertically blurred bloom view to a texture
6158 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);
6159 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6162 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6163 brighten = r_bloom_brighten.value;
6164 if (r_bloomstate.hdr)
6165 brighten *= r_hdr_range.value;
6166 brighten = sqrt(brighten);
6168 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6169 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6171 for (dir = 0;dir < 2;dir++)
6173 // blend on at multiple vertical offsets to achieve a vertical blur
6174 // TODO: do offset blends using GLSL
6175 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6176 GL_BlendFunc(GL_ONE, GL_ZERO);
6177 for (x = -range;x <= range;x++)
6179 if (!dir){xoffset = 0;yoffset = x;}
6180 else {xoffset = x;yoffset = 0;}
6181 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6182 yoffset /= (float)r_bloomstate.bloomtextureheight;
6183 // compute a texcoord array with the specified x and y offset
6184 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6185 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6186 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6187 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6188 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6189 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6190 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6191 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6192 // this r value looks like a 'dot' particle, fading sharply to
6193 // black at the edges
6194 // (probably not realistic but looks good enough)
6195 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6196 //r = brighten/(range*2+1);
6197 r = brighten / (range * 2 + 1);
6199 r *= (1 - x*x/(float)(range*range));
6200 GL_Color(r, r, r, 1);
6201 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6202 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6203 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6204 GL_BlendFunc(GL_ONE, GL_ONE);
6207 // copy the vertically blurred bloom view to a texture
6208 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);
6209 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6213 void R_HDR_RenderBloomTexture(void)
6215 int oldwidth, oldheight;
6216 float oldcolorscale;
6217 qboolean oldwaterstate;
6219 oldwaterstate = r_waterstate.enabled;
6220 oldcolorscale = r_refdef.view.colorscale;
6221 oldwidth = r_refdef.view.width;
6222 oldheight = r_refdef.view.height;
6223 r_refdef.view.width = r_bloomstate.bloomwidth;
6224 r_refdef.view.height = r_bloomstate.bloomheight;
6226 if(r_hdr.integer < 2)
6227 r_waterstate.enabled = false;
6229 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6230 // TODO: add exposure compensation features
6231 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6233 r_refdef.view.showdebug = false;
6234 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6236 R_ResetViewRendering3D();
6238 R_ClearScreen(r_refdef.fogenabled);
6239 if (r_timereport_active)
6240 R_TimeReport("HDRclear");
6243 if (r_timereport_active)
6244 R_TimeReport("visibility");
6246 // only do secondary renders with HDR if r_hdr is 2 or higher
6247 r_waterstate.numwaterplanes = 0;
6248 if (r_waterstate.enabled)
6249 R_RenderWaterPlanes();
6251 r_refdef.view.showdebug = true;
6253 r_waterstate.numwaterplanes = 0;
6255 R_ResetViewRendering2D();
6257 R_Bloom_CopyHDRTexture();
6258 R_Bloom_MakeTexture();
6260 // restore the view settings
6261 r_waterstate.enabled = oldwaterstate;
6262 r_refdef.view.width = oldwidth;
6263 r_refdef.view.height = oldheight;
6264 r_refdef.view.colorscale = oldcolorscale;
6266 R_ResetViewRendering3D();
6268 R_ClearScreen(r_refdef.fogenabled);
6269 if (r_timereport_active)
6270 R_TimeReport("viewclear");
6273 static void R_BlendView(void)
6275 unsigned int permutation;
6276 float uservecs[4][4];
6278 switch (vid.renderpath)
6280 case RENDERPATH_GL20:
6281 case RENDERPATH_D3D9:
6282 case RENDERPATH_D3D10:
6283 case RENDERPATH_D3D11:
6284 case RENDERPATH_SOFT:
6285 case RENDERPATH_GLES2:
6287 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6288 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6289 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6290 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6291 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6293 if (r_bloomstate.texture_screen)
6295 // make sure the buffer is available
6296 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6298 R_ResetViewRendering2D();
6299 R_Mesh_SetMainRenderTargets();
6301 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6303 // declare variables
6304 float blur_factor, blur_mouseaccel, blur_velocity;
6305 static float blur_average;
6306 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6308 // set a goal for the factoring
6309 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6310 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6311 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6312 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6313 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6314 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6316 // from the goal, pick an averaged value between goal and last value
6317 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6318 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6320 // enforce minimum amount of blur
6321 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6323 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6325 // calculate values into a standard alpha
6326 cl.motionbluralpha = 1 - exp(-
6328 (r_motionblur.value * blur_factor / 80)
6330 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6333 max(0.0001, cl.time - cl.oldtime) // fps independent
6336 // randomization for the blur value to combat persistent ghosting
6337 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6338 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6341 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6343 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6344 GL_Color(1, 1, 1, cl.motionbluralpha);
6345 switch(vid.renderpath)
6347 case RENDERPATH_GL11:
6348 case RENDERPATH_GL13:
6349 case RENDERPATH_GL20:
6350 case RENDERPATH_GLES1:
6351 case RENDERPATH_GLES2:
6352 case RENDERPATH_SOFT:
6353 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6355 case RENDERPATH_D3D9:
6356 case RENDERPATH_D3D10:
6357 case RENDERPATH_D3D11:
6358 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6361 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6362 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6363 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6366 // updates old view angles for next pass
6367 VectorCopy(cl.viewangles, blur_oldangles);
6370 // copy view into the screen texture
6371 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);
6372 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6374 else if (!r_bloomstate.texture_bloom)
6376 // we may still have to do view tint...
6377 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6379 // apply a color tint to the whole view
6380 R_ResetViewRendering2D();
6381 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6382 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6383 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6384 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6385 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6387 break; // no screen processing, no bloom, skip it
6390 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6392 // render simple bloom effect
6393 // copy the screen and shrink it and darken it for the bloom process
6394 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6395 // make the bloom texture
6396 R_Bloom_MakeTexture();
6399 #if _MSC_VER >= 1400
6400 #define sscanf sscanf_s
6402 memset(uservecs, 0, sizeof(uservecs));
6403 if (r_glsl_postprocess_uservec1_enable.integer)
6404 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6405 if (r_glsl_postprocess_uservec2_enable.integer)
6406 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6407 if (r_glsl_postprocess_uservec3_enable.integer)
6408 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6409 if (r_glsl_postprocess_uservec4_enable.integer)
6410 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6412 R_ResetViewRendering2D();
6413 GL_Color(1, 1, 1, 1);
6414 GL_BlendFunc(GL_ONE, GL_ZERO);
6416 switch(vid.renderpath)
6418 case RENDERPATH_GL20:
6419 case RENDERPATH_GLES2:
6420 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6421 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6422 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6423 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6424 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6425 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]);
6426 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6427 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]);
6428 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]);
6429 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]);
6430 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]);
6431 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6432 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6433 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);
6435 case RENDERPATH_D3D9:
6437 // 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...
6438 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6439 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6440 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6441 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6442 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6443 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6444 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6445 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6446 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6447 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6448 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6449 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6450 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6451 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6454 case RENDERPATH_D3D10:
6455 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6457 case RENDERPATH_D3D11:
6458 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6460 case RENDERPATH_SOFT:
6461 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6462 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6463 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6464 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6465 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6466 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6467 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6468 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6469 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6470 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6471 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6472 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6473 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6474 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6479 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6480 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6482 case RENDERPATH_GL11:
6483 case RENDERPATH_GL13:
6484 case RENDERPATH_GLES1:
6485 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6487 // apply a color tint to the whole view
6488 R_ResetViewRendering2D();
6489 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6490 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6491 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6492 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6493 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6499 matrix4x4_t r_waterscrollmatrix;
6501 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6503 if (r_refdef.fog_density)
6505 r_refdef.fogcolor[0] = r_refdef.fog_red;
6506 r_refdef.fogcolor[1] = r_refdef.fog_green;
6507 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6509 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6510 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6511 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6512 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6516 VectorCopy(r_refdef.fogcolor, fogvec);
6517 // color.rgb *= ContrastBoost * SceneBrightness;
6518 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6519 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6520 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6521 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6526 void R_UpdateVariables(void)
6530 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6532 r_refdef.farclip = r_farclip_base.value;
6533 if (r_refdef.scene.worldmodel)
6534 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6535 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6537 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6538 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6539 r_refdef.polygonfactor = 0;
6540 r_refdef.polygonoffset = 0;
6541 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6542 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6544 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6545 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6546 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6547 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6548 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6549 if (FAKELIGHT_ENABLED)
6551 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6553 if (r_showsurfaces.integer)
6555 r_refdef.scene.rtworld = false;
6556 r_refdef.scene.rtworldshadows = false;
6557 r_refdef.scene.rtdlight = false;
6558 r_refdef.scene.rtdlightshadows = false;
6559 r_refdef.lightmapintensity = 0;
6562 if (gamemode == GAME_NEHAHRA)
6564 if (gl_fogenable.integer)
6566 r_refdef.oldgl_fogenable = true;
6567 r_refdef.fog_density = gl_fogdensity.value;
6568 r_refdef.fog_red = gl_fogred.value;
6569 r_refdef.fog_green = gl_foggreen.value;
6570 r_refdef.fog_blue = gl_fogblue.value;
6571 r_refdef.fog_alpha = 1;
6572 r_refdef.fog_start = 0;
6573 r_refdef.fog_end = gl_skyclip.value;
6574 r_refdef.fog_height = 1<<30;
6575 r_refdef.fog_fadedepth = 128;
6577 else if (r_refdef.oldgl_fogenable)
6579 r_refdef.oldgl_fogenable = false;
6580 r_refdef.fog_density = 0;
6581 r_refdef.fog_red = 0;
6582 r_refdef.fog_green = 0;
6583 r_refdef.fog_blue = 0;
6584 r_refdef.fog_alpha = 0;
6585 r_refdef.fog_start = 0;
6586 r_refdef.fog_end = 0;
6587 r_refdef.fog_height = 1<<30;
6588 r_refdef.fog_fadedepth = 128;
6592 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6593 r_refdef.fog_start = max(0, r_refdef.fog_start);
6594 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6596 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6598 if (r_refdef.fog_density && r_drawfog.integer)
6600 r_refdef.fogenabled = true;
6601 // this is the point where the fog reaches 0.9986 alpha, which we
6602 // consider a good enough cutoff point for the texture
6603 // (0.9986 * 256 == 255.6)
6604 if (r_fog_exp2.integer)
6605 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6607 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6608 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6609 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6610 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6611 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6612 R_BuildFogHeightTexture();
6613 // fog color was already set
6614 // update the fog texture
6615 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)
6616 R_BuildFogTexture();
6617 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6618 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6621 r_refdef.fogenabled = false;
6623 switch(vid.renderpath)
6625 case RENDERPATH_GL20:
6626 case RENDERPATH_D3D9:
6627 case RENDERPATH_D3D10:
6628 case RENDERPATH_D3D11:
6629 case RENDERPATH_SOFT:
6630 case RENDERPATH_GLES2:
6631 if(v_glslgamma.integer && !vid_gammatables_trivial)
6633 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6635 // build GLSL gamma texture
6636 #define RAMPWIDTH 256
6637 unsigned short ramp[RAMPWIDTH * 3];
6638 unsigned char rampbgr[RAMPWIDTH][4];
6641 r_texture_gammaramps_serial = vid_gammatables_serial;
6643 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6644 for(i = 0; i < RAMPWIDTH; ++i)
6646 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6647 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6648 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6651 if (r_texture_gammaramps)
6653 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6657 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6663 // remove GLSL gamma texture
6666 case RENDERPATH_GL11:
6667 case RENDERPATH_GL13:
6668 case RENDERPATH_GLES1:
6673 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6674 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6680 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6681 if( scenetype != r_currentscenetype ) {
6682 // store the old scenetype
6683 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6684 r_currentscenetype = scenetype;
6685 // move in the new scene
6686 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6695 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6697 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6698 if( scenetype == r_currentscenetype ) {
6699 return &r_refdef.scene;
6701 return &r_scenes_store[ scenetype ];
6710 int dpsoftrast_test;
6711 extern void R_Shadow_UpdateBounceGridTexture(void);
6712 extern cvar_t r_shadow_bouncegrid;
6713 void R_RenderView(void)
6715 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6717 dpsoftrast_test = r_test.integer;
6719 if (r_timereport_active)
6720 R_TimeReport("start");
6721 r_textureframe++; // used only by R_GetCurrentTexture
6722 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6724 if(R_CompileShader_CheckStaticParms())
6727 if (!r_drawentities.integer)
6728 r_refdef.scene.numentities = 0;
6730 R_AnimCache_ClearCache();
6731 R_FrameData_NewFrame();
6733 /* adjust for stereo display */
6734 if(R_Stereo_Active())
6736 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);
6737 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6740 if (r_refdef.view.isoverlay)
6742 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6743 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6744 R_TimeReport("depthclear");
6746 r_refdef.view.showdebug = false;
6748 r_waterstate.enabled = false;
6749 r_waterstate.numwaterplanes = 0;
6753 r_refdef.view.matrix = originalmatrix;
6759 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6761 r_refdef.view.matrix = originalmatrix;
6762 return; //Host_Error ("R_RenderView: NULL worldmodel");
6765 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6767 R_RenderView_UpdateViewVectors();
6769 R_Shadow_UpdateWorldLightSelection();
6771 R_Bloom_StartFrame();
6772 R_Water_StartFrame();
6775 if (r_timereport_active)
6776 R_TimeReport("viewsetup");
6778 R_ResetViewRendering3D();
6780 if (r_refdef.view.clear || r_refdef.fogenabled)
6782 R_ClearScreen(r_refdef.fogenabled);
6783 if (r_timereport_active)
6784 R_TimeReport("viewclear");
6786 r_refdef.view.clear = true;
6788 // this produces a bloom texture to be used in R_BlendView() later
6789 if (r_bloomstate.hdr)
6791 R_HDR_RenderBloomTexture();
6792 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6793 r_textureframe++; // used only by R_GetCurrentTexture
6796 r_refdef.view.showdebug = true;
6799 if (r_timereport_active)
6800 R_TimeReport("visibility");
6802 R_Shadow_UpdateBounceGridTexture();
6803 if (r_timereport_active && r_shadow_bouncegrid.integer)
6804 R_TimeReport("bouncegrid");
6806 r_waterstate.numwaterplanes = 0;
6807 if (r_waterstate.enabled)
6808 R_RenderWaterPlanes();
6811 r_waterstate.numwaterplanes = 0;
6814 if (r_timereport_active)
6815 R_TimeReport("blendview");
6817 GL_Scissor(0, 0, vid.width, vid.height);
6818 GL_ScissorTest(false);
6820 r_refdef.view.matrix = originalmatrix;
6825 void R_RenderWaterPlanes(void)
6827 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6829 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6830 if (r_timereport_active)
6831 R_TimeReport("waterworld");
6834 // don't let sound skip if going slow
6835 if (r_refdef.scene.extraupdate)
6838 R_DrawModelsAddWaterPlanes();
6839 if (r_timereport_active)
6840 R_TimeReport("watermodels");
6842 if (r_waterstate.numwaterplanes)
6844 R_Water_ProcessPlanes();
6845 if (r_timereport_active)
6846 R_TimeReport("waterscenes");
6850 extern void R_DrawLightningBeams (void);
6851 extern void VM_CL_AddPolygonsToMeshQueue (void);
6852 extern void R_DrawPortals (void);
6853 extern cvar_t cl_locs_show;
6854 static void R_DrawLocs(void);
6855 static void R_DrawEntityBBoxes(void);
6856 static void R_DrawModelDecals(void);
6857 extern void R_DrawModelShadows(void);
6858 extern void R_DrawModelShadowMaps(void);
6859 extern cvar_t cl_decals_newsystem;
6860 extern qboolean r_shadow_usingdeferredprepass;
6861 void R_RenderScene(void)
6863 qboolean shadowmapping = false;
6865 if (r_timereport_active)
6866 R_TimeReport("beginscene");
6868 r_refdef.stats.renders++;
6872 // don't let sound skip if going slow
6873 if (r_refdef.scene.extraupdate)
6876 R_MeshQueue_BeginScene();
6880 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);
6882 if (r_timereport_active)
6883 R_TimeReport("skystartframe");
6885 if (cl.csqc_vidvars.drawworld)
6887 // don't let sound skip if going slow
6888 if (r_refdef.scene.extraupdate)
6891 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6893 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6894 if (r_timereport_active)
6895 R_TimeReport("worldsky");
6898 if (R_DrawBrushModelsSky() && r_timereport_active)
6899 R_TimeReport("bmodelsky");
6901 if (skyrendermasked && skyrenderlater)
6903 // we have to force off the water clipping plane while rendering sky
6907 if (r_timereport_active)
6908 R_TimeReport("sky");
6912 R_AnimCache_CacheVisibleEntities();
6913 if (r_timereport_active)
6914 R_TimeReport("animation");
6916 R_Shadow_PrepareLights();
6917 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6918 R_Shadow_PrepareModelShadows();
6919 if (r_timereport_active)
6920 R_TimeReport("preparelights");
6922 if (R_Shadow_ShadowMappingEnabled())
6923 shadowmapping = true;
6925 if (r_shadow_usingdeferredprepass)
6926 R_Shadow_DrawPrepass();
6928 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6930 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6931 if (r_timereport_active)
6932 R_TimeReport("worlddepth");
6934 if (r_depthfirst.integer >= 2)
6936 R_DrawModelsDepth();
6937 if (r_timereport_active)
6938 R_TimeReport("modeldepth");
6941 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6943 R_DrawModelShadowMaps();
6944 R_ResetViewRendering3D();
6945 // don't let sound skip if going slow
6946 if (r_refdef.scene.extraupdate)
6950 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6952 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6953 if (r_timereport_active)
6954 R_TimeReport("world");
6957 // don't let sound skip if going slow
6958 if (r_refdef.scene.extraupdate)
6962 if (r_timereport_active)
6963 R_TimeReport("models");
6965 // don't let sound skip if going slow
6966 if (r_refdef.scene.extraupdate)
6969 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6971 R_DrawModelShadows();
6972 R_ResetViewRendering3D();
6973 // don't let sound skip if going slow
6974 if (r_refdef.scene.extraupdate)
6978 if (!r_shadow_usingdeferredprepass)
6980 R_Shadow_DrawLights();
6981 if (r_timereport_active)
6982 R_TimeReport("rtlights");
6985 // don't let sound skip if going slow
6986 if (r_refdef.scene.extraupdate)
6989 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6991 R_DrawModelShadows();
6992 R_ResetViewRendering3D();
6993 // don't let sound skip if going slow
6994 if (r_refdef.scene.extraupdate)
6998 if (cl.csqc_vidvars.drawworld)
7000 if (cl_decals_newsystem.integer)
7002 R_DrawModelDecals();
7003 if (r_timereport_active)
7004 R_TimeReport("modeldecals");
7009 if (r_timereport_active)
7010 R_TimeReport("decals");
7014 if (r_timereport_active)
7015 R_TimeReport("particles");
7018 if (r_timereport_active)
7019 R_TimeReport("explosions");
7021 R_DrawLightningBeams();
7022 if (r_timereport_active)
7023 R_TimeReport("lightning");
7026 VM_CL_AddPolygonsToMeshQueue();
7028 if (r_refdef.view.showdebug)
7030 if (cl_locs_show.integer)
7033 if (r_timereport_active)
7034 R_TimeReport("showlocs");
7037 if (r_drawportals.integer)
7040 if (r_timereport_active)
7041 R_TimeReport("portals");
7044 if (r_showbboxes.value > 0)
7046 R_DrawEntityBBoxes();
7047 if (r_timereport_active)
7048 R_TimeReport("bboxes");
7052 if (r_transparent.integer)
7054 R_MeshQueue_RenderTransparent();
7055 if (r_timereport_active)
7056 R_TimeReport("drawtrans");
7059 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))
7061 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7062 if (r_timereport_active)
7063 R_TimeReport("worlddebug");
7064 R_DrawModelsDebug();
7065 if (r_timereport_active)
7066 R_TimeReport("modeldebug");
7069 if (cl.csqc_vidvars.drawworld)
7071 R_Shadow_DrawCoronas();
7072 if (r_timereport_active)
7073 R_TimeReport("coronas");
7078 GL_DepthTest(false);
7079 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7080 GL_Color(1, 1, 1, 1);
7081 qglBegin(GL_POLYGON);
7082 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7083 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7084 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7085 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7087 qglBegin(GL_POLYGON);
7088 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]);
7089 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]);
7090 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]);
7091 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]);
7093 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7097 // don't let sound skip if going slow
7098 if (r_refdef.scene.extraupdate)
7101 R_ResetViewRendering2D();
7104 static const unsigned short bboxelements[36] =
7114 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7117 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7119 RSurf_ActiveWorldEntity();
7121 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7122 GL_DepthMask(false);
7123 GL_DepthRange(0, 1);
7124 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7125 // R_Mesh_ResetTextureState();
7127 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7128 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7129 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7130 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7131 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7132 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7133 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7134 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7135 R_FillColors(color4f, 8, cr, cg, cb, ca);
7136 if (r_refdef.fogenabled)
7138 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7140 f1 = RSurf_FogVertex(v);
7142 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7143 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7144 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7147 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7148 R_Mesh_ResetTextureState();
7149 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7150 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7153 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7157 prvm_edict_t *edict;
7158 prvm_prog_t *prog_save = prog;
7160 // this function draws bounding boxes of server entities
7164 GL_CullFace(GL_NONE);
7165 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7169 for (i = 0;i < numsurfaces;i++)
7171 edict = PRVM_EDICT_NUM(surfacelist[i]);
7172 switch ((int)PRVM_serveredictfloat(edict, solid))
7174 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7175 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7176 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7177 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7178 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7179 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7181 color[3] *= r_showbboxes.value;
7182 color[3] = bound(0, color[3], 1);
7183 GL_DepthTest(!r_showdisabledepthtest.integer);
7184 GL_CullFace(r_refdef.view.cullface_front);
7185 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7191 static void R_DrawEntityBBoxes(void)
7194 prvm_edict_t *edict;
7196 prvm_prog_t *prog_save = prog;
7198 // this function draws bounding boxes of server entities
7204 for (i = 0;i < prog->num_edicts;i++)
7206 edict = PRVM_EDICT_NUM(i);
7207 if (edict->priv.server->free)
7209 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7210 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7212 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7214 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7215 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7221 static const int nomodelelement3i[24] =
7233 static const unsigned short nomodelelement3s[24] =
7245 static const float nomodelvertex3f[6*3] =
7255 static const float nomodelcolor4f[6*4] =
7257 0.0f, 0.0f, 0.5f, 1.0f,
7258 0.0f, 0.0f, 0.5f, 1.0f,
7259 0.0f, 0.5f, 0.0f, 1.0f,
7260 0.0f, 0.5f, 0.0f, 1.0f,
7261 0.5f, 0.0f, 0.0f, 1.0f,
7262 0.5f, 0.0f, 0.0f, 1.0f
7265 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7271 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);
7273 // this is only called once per entity so numsurfaces is always 1, and
7274 // surfacelist is always {0}, so this code does not handle batches
7276 if (rsurface.ent_flags & RENDER_ADDITIVE)
7278 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7279 GL_DepthMask(false);
7281 else if (rsurface.colormod[3] < 1)
7283 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7284 GL_DepthMask(false);
7288 GL_BlendFunc(GL_ONE, GL_ZERO);
7291 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7292 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7293 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7294 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7295 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7296 for (i = 0, c = color4f;i < 6;i++, c += 4)
7298 c[0] *= rsurface.colormod[0];
7299 c[1] *= rsurface.colormod[1];
7300 c[2] *= rsurface.colormod[2];
7301 c[3] *= rsurface.colormod[3];
7303 if (r_refdef.fogenabled)
7305 for (i = 0, c = color4f;i < 6;i++, c += 4)
7307 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7309 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7310 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7311 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7314 // R_Mesh_ResetTextureState();
7315 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7316 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7317 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7320 void R_DrawNoModel(entity_render_t *ent)
7323 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7324 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7325 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7327 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7330 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7332 vec3_t right1, right2, diff, normal;
7334 VectorSubtract (org2, org1, normal);
7336 // calculate 'right' vector for start
7337 VectorSubtract (r_refdef.view.origin, org1, diff);
7338 CrossProduct (normal, diff, right1);
7339 VectorNormalize (right1);
7341 // calculate 'right' vector for end
7342 VectorSubtract (r_refdef.view.origin, org2, diff);
7343 CrossProduct (normal, diff, right2);
7344 VectorNormalize (right2);
7346 vert[ 0] = org1[0] + width * right1[0];
7347 vert[ 1] = org1[1] + width * right1[1];
7348 vert[ 2] = org1[2] + width * right1[2];
7349 vert[ 3] = org1[0] - width * right1[0];
7350 vert[ 4] = org1[1] - width * right1[1];
7351 vert[ 5] = org1[2] - width * right1[2];
7352 vert[ 6] = org2[0] - width * right2[0];
7353 vert[ 7] = org2[1] - width * right2[1];
7354 vert[ 8] = org2[2] - width * right2[2];
7355 vert[ 9] = org2[0] + width * right2[0];
7356 vert[10] = org2[1] + width * right2[1];
7357 vert[11] = org2[2] + width * right2[2];
7360 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)
7362 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7363 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7364 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7365 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7366 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7367 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7368 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7369 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7370 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7371 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7372 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7373 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7376 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7381 VectorSet(v, x, y, z);
7382 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7383 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7385 if (i == mesh->numvertices)
7387 if (mesh->numvertices < mesh->maxvertices)
7389 VectorCopy(v, vertex3f);
7390 mesh->numvertices++;
7392 return mesh->numvertices;
7398 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7402 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7403 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7404 e = mesh->element3i + mesh->numtriangles * 3;
7405 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7407 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7408 if (mesh->numtriangles < mesh->maxtriangles)
7413 mesh->numtriangles++;
7415 element[1] = element[2];
7419 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7423 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7424 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7425 e = mesh->element3i + mesh->numtriangles * 3;
7426 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7428 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7429 if (mesh->numtriangles < mesh->maxtriangles)
7434 mesh->numtriangles++;
7436 element[1] = element[2];
7440 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7441 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7443 int planenum, planenum2;
7446 mplane_t *plane, *plane2;
7448 double temppoints[2][256*3];
7449 // figure out how large a bounding box we need to properly compute this brush
7451 for (w = 0;w < numplanes;w++)
7452 maxdist = max(maxdist, fabs(planes[w].dist));
7453 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7454 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7455 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7459 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7460 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7462 if (planenum2 == planenum)
7464 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);
7467 if (tempnumpoints < 3)
7469 // generate elements forming a triangle fan for this polygon
7470 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7474 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)
7476 texturelayer_t *layer;
7477 layer = t->currentlayers + t->currentnumlayers++;
7479 layer->depthmask = depthmask;
7480 layer->blendfunc1 = blendfunc1;
7481 layer->blendfunc2 = blendfunc2;
7482 layer->texture = texture;
7483 layer->texmatrix = *matrix;
7484 layer->color[0] = r;
7485 layer->color[1] = g;
7486 layer->color[2] = b;
7487 layer->color[3] = a;
7490 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7492 if(parms[0] == 0 && parms[1] == 0)
7494 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7495 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7500 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7503 index = parms[2] + rsurface.shadertime * parms[3];
7504 index -= floor(index);
7505 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7508 case Q3WAVEFUNC_NONE:
7509 case Q3WAVEFUNC_NOISE:
7510 case Q3WAVEFUNC_COUNT:
7513 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7514 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7515 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7516 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7517 case Q3WAVEFUNC_TRIANGLE:
7519 f = index - floor(index);
7532 f = parms[0] + parms[1] * f;
7533 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7534 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7538 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7544 matrix4x4_t matrix, temp;
7545 switch(tcmod->tcmod)
7549 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7550 matrix = r_waterscrollmatrix;
7552 matrix = identitymatrix;
7554 case Q3TCMOD_ENTITYTRANSLATE:
7555 // this is used in Q3 to allow the gamecode to control texcoord
7556 // scrolling on the entity, which is not supported in darkplaces yet.
7557 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7559 case Q3TCMOD_ROTATE:
7560 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7561 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7562 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7565 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7567 case Q3TCMOD_SCROLL:
7568 // extra care is needed because of precision breakdown with large values of time
7569 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7570 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7571 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7573 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7574 w = (int) tcmod->parms[0];
7575 h = (int) tcmod->parms[1];
7576 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7578 idx = (int) floor(f * w * h);
7579 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7581 case Q3TCMOD_STRETCH:
7582 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7583 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7585 case Q3TCMOD_TRANSFORM:
7586 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7587 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7588 VectorSet(tcmat + 6, 0 , 0 , 1);
7589 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7590 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7592 case Q3TCMOD_TURBULENT:
7593 // this is handled in the RSurf_PrepareVertices function
7594 matrix = identitymatrix;
7598 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7601 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7603 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7604 char name[MAX_QPATH];
7605 skinframe_t *skinframe;
7606 unsigned char pixels[296*194];
7607 strlcpy(cache->name, skinname, sizeof(cache->name));
7608 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7609 if (developer_loading.integer)
7610 Con_Printf("loading %s\n", name);
7611 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7612 if (!skinframe || !skinframe->base)
7615 fs_offset_t filesize;
7617 f = FS_LoadFile(name, tempmempool, true, &filesize);
7620 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7621 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7625 cache->skinframe = skinframe;
7628 texture_t *R_GetCurrentTexture(texture_t *t)
7631 const entity_render_t *ent = rsurface.entity;
7632 dp_model_t *model = ent->model;
7633 q3shaderinfo_layer_tcmod_t *tcmod;
7635 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7636 return t->currentframe;
7637 t->update_lastrenderframe = r_textureframe;
7638 t->update_lastrenderentity = (void *)ent;
7640 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7641 t->camera_entity = ent->entitynumber;
7643 t->camera_entity = 0;
7645 // switch to an alternate material if this is a q1bsp animated material
7647 texture_t *texture = t;
7648 int s = rsurface.ent_skinnum;
7649 if ((unsigned int)s >= (unsigned int)model->numskins)
7651 if (model->skinscenes)
7653 if (model->skinscenes[s].framecount > 1)
7654 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7656 s = model->skinscenes[s].firstframe;
7659 t = t + s * model->num_surfaces;
7662 // use an alternate animation if the entity's frame is not 0,
7663 // and only if the texture has an alternate animation
7664 if (rsurface.ent_alttextures && t->anim_total[1])
7665 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7667 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7669 texture->currentframe = t;
7672 // update currentskinframe to be a qw skin or animation frame
7673 if (rsurface.ent_qwskin >= 0)
7675 i = rsurface.ent_qwskin;
7676 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7678 r_qwskincache_size = cl.maxclients;
7680 Mem_Free(r_qwskincache);
7681 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7683 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7684 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7685 t->currentskinframe = r_qwskincache[i].skinframe;
7686 if (t->currentskinframe == NULL)
7687 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7689 else if (t->numskinframes >= 2)
7690 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7691 if (t->backgroundnumskinframes >= 2)
7692 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7694 t->currentmaterialflags = t->basematerialflags;
7695 t->currentalpha = rsurface.colormod[3];
7696 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7697 t->currentalpha *= r_wateralpha.value;
7698 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7699 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7700 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7701 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7702 if (!(rsurface.ent_flags & RENDER_LIGHT))
7703 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7704 else if (FAKELIGHT_ENABLED)
7706 // no modellight if using fakelight for the map
7708 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7710 // pick a model lighting mode
7711 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7712 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7714 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7716 if (rsurface.ent_flags & RENDER_ADDITIVE)
7717 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7718 else if (t->currentalpha < 1)
7719 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7720 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7721 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7722 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7723 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7724 if (t->backgroundnumskinframes)
7725 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7726 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7728 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7729 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7732 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7733 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7735 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7736 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7738 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7739 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7741 // there is no tcmod
7742 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7744 t->currenttexmatrix = r_waterscrollmatrix;
7745 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7747 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7749 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7750 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7753 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7754 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7755 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7756 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7758 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7759 if (t->currentskinframe->qpixels)
7760 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7761 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7762 if (!t->basetexture)
7763 t->basetexture = r_texture_notexture;
7764 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7765 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7766 t->nmaptexture = t->currentskinframe->nmap;
7767 if (!t->nmaptexture)
7768 t->nmaptexture = r_texture_blanknormalmap;
7769 t->glosstexture = r_texture_black;
7770 t->glowtexture = t->currentskinframe->glow;
7771 t->fogtexture = t->currentskinframe->fog;
7772 t->reflectmasktexture = t->currentskinframe->reflect;
7773 if (t->backgroundnumskinframes)
7775 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7776 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7777 t->backgroundglosstexture = r_texture_black;
7778 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7779 if (!t->backgroundnmaptexture)
7780 t->backgroundnmaptexture = r_texture_blanknormalmap;
7784 t->backgroundbasetexture = r_texture_white;
7785 t->backgroundnmaptexture = r_texture_blanknormalmap;
7786 t->backgroundglosstexture = r_texture_black;
7787 t->backgroundglowtexture = NULL;
7789 t->specularpower = r_shadow_glossexponent.value;
7790 // TODO: store reference values for these in the texture?
7791 t->specularscale = 0;
7792 if (r_shadow_gloss.integer > 0)
7794 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7796 if (r_shadow_glossintensity.value > 0)
7798 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7799 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7800 t->specularscale = r_shadow_glossintensity.value;
7803 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7805 t->glosstexture = r_texture_white;
7806 t->backgroundglosstexture = r_texture_white;
7807 t->specularscale = r_shadow_gloss2intensity.value;
7808 t->specularpower = r_shadow_gloss2exponent.value;
7811 t->specularscale *= t->specularscalemod;
7812 t->specularpower *= t->specularpowermod;
7814 // lightmaps mode looks bad with dlights using actual texturing, so turn
7815 // off the colormap and glossmap, but leave the normalmap on as it still
7816 // accurately represents the shading involved
7817 if (gl_lightmaps.integer)
7819 t->basetexture = r_texture_grey128;
7820 t->pantstexture = r_texture_black;
7821 t->shirttexture = r_texture_black;
7822 t->nmaptexture = r_texture_blanknormalmap;
7823 t->glosstexture = r_texture_black;
7824 t->glowtexture = NULL;
7825 t->fogtexture = NULL;
7826 t->reflectmasktexture = NULL;
7827 t->backgroundbasetexture = NULL;
7828 t->backgroundnmaptexture = r_texture_blanknormalmap;
7829 t->backgroundglosstexture = r_texture_black;
7830 t->backgroundglowtexture = NULL;
7831 t->specularscale = 0;
7832 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7835 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7836 VectorClear(t->dlightcolor);
7837 t->currentnumlayers = 0;
7838 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7840 int blendfunc1, blendfunc2;
7842 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7844 blendfunc1 = GL_SRC_ALPHA;
7845 blendfunc2 = GL_ONE;
7847 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7849 blendfunc1 = GL_SRC_ALPHA;
7850 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7852 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7854 blendfunc1 = t->customblendfunc[0];
7855 blendfunc2 = t->customblendfunc[1];
7859 blendfunc1 = GL_ONE;
7860 blendfunc2 = GL_ZERO;
7862 // don't colormod evilblend textures
7863 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7864 VectorSet(t->lightmapcolor, 1, 1, 1);
7865 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7866 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7868 // fullbright is not affected by r_refdef.lightmapintensity
7869 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]);
7870 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7871 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]);
7872 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7873 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]);
7877 vec3_t ambientcolor;
7879 // set the color tint used for lights affecting this surface
7880 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7882 // q3bsp has no lightmap updates, so the lightstylevalue that
7883 // would normally be baked into the lightmap must be
7884 // applied to the color
7885 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7886 if (model->type == mod_brushq3)
7887 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7888 colorscale *= r_refdef.lightmapintensity;
7889 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7890 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7891 // basic lit geometry
7892 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]);
7893 // add pants/shirt if needed
7894 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7895 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]);
7896 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7897 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]);
7898 // now add ambient passes if needed
7899 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7901 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]);
7902 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7903 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]);
7904 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7905 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]);
7908 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7909 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]);
7910 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7912 // if this is opaque use alpha blend which will darken the earlier
7915 // if this is an alpha blended material, all the earlier passes
7916 // were darkened by fog already, so we only need to add the fog
7917 // color ontop through the fog mask texture
7919 // if this is an additive blended material, all the earlier passes
7920 // were darkened by fog already, and we should not add fog color
7921 // (because the background was not darkened, there is no fog color
7922 // that was lost behind it).
7923 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]);
7927 return t->currentframe;
7930 rsurfacestate_t rsurface;
7932 void RSurf_ActiveWorldEntity(void)
7934 dp_model_t *model = r_refdef.scene.worldmodel;
7935 //if (rsurface.entity == r_refdef.scene.worldentity)
7937 rsurface.entity = r_refdef.scene.worldentity;
7938 rsurface.skeleton = NULL;
7939 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7940 rsurface.ent_skinnum = 0;
7941 rsurface.ent_qwskin = -1;
7942 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7943 rsurface.shadertime = r_refdef.scene.time;
7944 rsurface.matrix = identitymatrix;
7945 rsurface.inversematrix = identitymatrix;
7946 rsurface.matrixscale = 1;
7947 rsurface.inversematrixscale = 1;
7948 R_EntityMatrix(&identitymatrix);
7949 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7950 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7951 rsurface.fograngerecip = r_refdef.fograngerecip;
7952 rsurface.fogheightfade = r_refdef.fogheightfade;
7953 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7954 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7955 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7956 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7957 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7958 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7959 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7960 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7961 rsurface.colormod[3] = 1;
7962 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);
7963 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7964 rsurface.frameblend[0].lerp = 1;
7965 rsurface.ent_alttextures = false;
7966 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7967 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7968 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7969 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7970 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7971 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7972 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7973 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7974 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7975 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7976 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7977 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7978 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7979 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7980 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7981 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7982 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7983 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7984 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7985 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7986 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7987 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7988 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7989 rsurface.modelelement3i = model->surfmesh.data_element3i;
7990 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7991 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7992 rsurface.modelelement3s = model->surfmesh.data_element3s;
7993 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7994 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7995 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7996 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7997 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7998 rsurface.modelsurfaces = model->data_surfaces;
7999 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8000 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8001 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8002 rsurface.modelgeneratedvertex = false;
8003 rsurface.batchgeneratedvertex = false;
8004 rsurface.batchfirstvertex = 0;
8005 rsurface.batchnumvertices = 0;
8006 rsurface.batchfirsttriangle = 0;
8007 rsurface.batchnumtriangles = 0;
8008 rsurface.batchvertex3f = NULL;
8009 rsurface.batchvertex3f_vertexbuffer = NULL;
8010 rsurface.batchvertex3f_bufferoffset = 0;
8011 rsurface.batchsvector3f = NULL;
8012 rsurface.batchsvector3f_vertexbuffer = NULL;
8013 rsurface.batchsvector3f_bufferoffset = 0;
8014 rsurface.batchtvector3f = NULL;
8015 rsurface.batchtvector3f_vertexbuffer = NULL;
8016 rsurface.batchtvector3f_bufferoffset = 0;
8017 rsurface.batchnormal3f = NULL;
8018 rsurface.batchnormal3f_vertexbuffer = NULL;
8019 rsurface.batchnormal3f_bufferoffset = 0;
8020 rsurface.batchlightmapcolor4f = NULL;
8021 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8022 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8023 rsurface.batchtexcoordtexture2f = NULL;
8024 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8025 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8026 rsurface.batchtexcoordlightmap2f = NULL;
8027 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8028 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8029 rsurface.batchvertexmesh = NULL;
8030 rsurface.batchvertexmeshbuffer = NULL;
8031 rsurface.batchvertex3fbuffer = NULL;
8032 rsurface.batchelement3i = NULL;
8033 rsurface.batchelement3i_indexbuffer = NULL;
8034 rsurface.batchelement3i_bufferoffset = 0;
8035 rsurface.batchelement3s = NULL;
8036 rsurface.batchelement3s_indexbuffer = NULL;
8037 rsurface.batchelement3s_bufferoffset = 0;
8038 rsurface.passcolor4f = NULL;
8039 rsurface.passcolor4f_vertexbuffer = NULL;
8040 rsurface.passcolor4f_bufferoffset = 0;
8043 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8045 dp_model_t *model = ent->model;
8046 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8048 rsurface.entity = (entity_render_t *)ent;
8049 rsurface.skeleton = ent->skeleton;
8050 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8051 rsurface.ent_skinnum = ent->skinnum;
8052 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;
8053 rsurface.ent_flags = ent->flags;
8054 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8055 rsurface.matrix = ent->matrix;
8056 rsurface.inversematrix = ent->inversematrix;
8057 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8058 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8059 R_EntityMatrix(&rsurface.matrix);
8060 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8061 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8062 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8063 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8064 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8065 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8066 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8067 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8068 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8069 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8070 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8071 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8072 rsurface.colormod[3] = ent->alpha;
8073 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8074 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8075 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8076 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8077 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8078 if (ent->model->brush.submodel && !prepass)
8080 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8081 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8083 if (model->surfmesh.isanimated && model->AnimateVertices)
8085 if (ent->animcache_vertex3f)
8087 rsurface.modelvertex3f = ent->animcache_vertex3f;
8088 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8089 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8090 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8091 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8092 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8093 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8095 else if (wanttangents)
8097 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8098 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8099 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8100 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8101 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8102 rsurface.modelvertexmesh = NULL;
8103 rsurface.modelvertexmeshbuffer = NULL;
8104 rsurface.modelvertex3fbuffer = NULL;
8106 else if (wantnormals)
8108 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8109 rsurface.modelsvector3f = NULL;
8110 rsurface.modeltvector3f = NULL;
8111 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8112 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8113 rsurface.modelvertexmesh = NULL;
8114 rsurface.modelvertexmeshbuffer = NULL;
8115 rsurface.modelvertex3fbuffer = NULL;
8119 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8120 rsurface.modelsvector3f = NULL;
8121 rsurface.modeltvector3f = NULL;
8122 rsurface.modelnormal3f = NULL;
8123 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8124 rsurface.modelvertexmesh = NULL;
8125 rsurface.modelvertexmeshbuffer = NULL;
8126 rsurface.modelvertex3fbuffer = NULL;
8128 rsurface.modelvertex3f_vertexbuffer = 0;
8129 rsurface.modelvertex3f_bufferoffset = 0;
8130 rsurface.modelsvector3f_vertexbuffer = 0;
8131 rsurface.modelsvector3f_bufferoffset = 0;
8132 rsurface.modeltvector3f_vertexbuffer = 0;
8133 rsurface.modeltvector3f_bufferoffset = 0;
8134 rsurface.modelnormal3f_vertexbuffer = 0;
8135 rsurface.modelnormal3f_bufferoffset = 0;
8136 rsurface.modelgeneratedvertex = true;
8140 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8141 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8142 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8143 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8144 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8145 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8146 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8147 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8148 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8149 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8150 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8151 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8152 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8153 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8154 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8155 rsurface.modelgeneratedvertex = false;
8157 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8158 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8159 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8160 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8161 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8162 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8163 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8164 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8165 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8166 rsurface.modelelement3i = model->surfmesh.data_element3i;
8167 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8168 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8169 rsurface.modelelement3s = model->surfmesh.data_element3s;
8170 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8171 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8172 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8173 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8174 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8175 rsurface.modelsurfaces = model->data_surfaces;
8176 rsurface.batchgeneratedvertex = false;
8177 rsurface.batchfirstvertex = 0;
8178 rsurface.batchnumvertices = 0;
8179 rsurface.batchfirsttriangle = 0;
8180 rsurface.batchnumtriangles = 0;
8181 rsurface.batchvertex3f = NULL;
8182 rsurface.batchvertex3f_vertexbuffer = NULL;
8183 rsurface.batchvertex3f_bufferoffset = 0;
8184 rsurface.batchsvector3f = NULL;
8185 rsurface.batchsvector3f_vertexbuffer = NULL;
8186 rsurface.batchsvector3f_bufferoffset = 0;
8187 rsurface.batchtvector3f = NULL;
8188 rsurface.batchtvector3f_vertexbuffer = NULL;
8189 rsurface.batchtvector3f_bufferoffset = 0;
8190 rsurface.batchnormal3f = NULL;
8191 rsurface.batchnormal3f_vertexbuffer = NULL;
8192 rsurface.batchnormal3f_bufferoffset = 0;
8193 rsurface.batchlightmapcolor4f = NULL;
8194 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8195 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8196 rsurface.batchtexcoordtexture2f = NULL;
8197 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8198 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8199 rsurface.batchtexcoordlightmap2f = NULL;
8200 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8201 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8202 rsurface.batchvertexmesh = NULL;
8203 rsurface.batchvertexmeshbuffer = NULL;
8204 rsurface.batchvertex3fbuffer = NULL;
8205 rsurface.batchelement3i = NULL;
8206 rsurface.batchelement3i_indexbuffer = NULL;
8207 rsurface.batchelement3i_bufferoffset = 0;
8208 rsurface.batchelement3s = NULL;
8209 rsurface.batchelement3s_indexbuffer = NULL;
8210 rsurface.batchelement3s_bufferoffset = 0;
8211 rsurface.passcolor4f = NULL;
8212 rsurface.passcolor4f_vertexbuffer = NULL;
8213 rsurface.passcolor4f_bufferoffset = 0;
8216 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)
8218 rsurface.entity = r_refdef.scene.worldentity;
8219 rsurface.skeleton = NULL;
8220 rsurface.ent_skinnum = 0;
8221 rsurface.ent_qwskin = -1;
8222 rsurface.ent_flags = entflags;
8223 rsurface.shadertime = r_refdef.scene.time - shadertime;
8224 rsurface.modelnumvertices = numvertices;
8225 rsurface.modelnumtriangles = numtriangles;
8226 rsurface.matrix = *matrix;
8227 rsurface.inversematrix = *inversematrix;
8228 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8229 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8230 R_EntityMatrix(&rsurface.matrix);
8231 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8232 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8233 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8234 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8235 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8236 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8237 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8238 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8239 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8240 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8241 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8242 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8243 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);
8244 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8245 rsurface.frameblend[0].lerp = 1;
8246 rsurface.ent_alttextures = false;
8247 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8248 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8251 rsurface.modelvertex3f = (float *)vertex3f;
8252 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8253 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8254 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8256 else if (wantnormals)
8258 rsurface.modelvertex3f = (float *)vertex3f;
8259 rsurface.modelsvector3f = NULL;
8260 rsurface.modeltvector3f = NULL;
8261 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8265 rsurface.modelvertex3f = (float *)vertex3f;
8266 rsurface.modelsvector3f = NULL;
8267 rsurface.modeltvector3f = NULL;
8268 rsurface.modelnormal3f = NULL;
8270 rsurface.modelvertexmesh = NULL;
8271 rsurface.modelvertexmeshbuffer = NULL;
8272 rsurface.modelvertex3fbuffer = NULL;
8273 rsurface.modelvertex3f_vertexbuffer = 0;
8274 rsurface.modelvertex3f_bufferoffset = 0;
8275 rsurface.modelsvector3f_vertexbuffer = 0;
8276 rsurface.modelsvector3f_bufferoffset = 0;
8277 rsurface.modeltvector3f_vertexbuffer = 0;
8278 rsurface.modeltvector3f_bufferoffset = 0;
8279 rsurface.modelnormal3f_vertexbuffer = 0;
8280 rsurface.modelnormal3f_bufferoffset = 0;
8281 rsurface.modelgeneratedvertex = true;
8282 rsurface.modellightmapcolor4f = (float *)color4f;
8283 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8284 rsurface.modellightmapcolor4f_bufferoffset = 0;
8285 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8286 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8287 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8288 rsurface.modeltexcoordlightmap2f = NULL;
8289 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8290 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8291 rsurface.modelelement3i = (int *)element3i;
8292 rsurface.modelelement3i_indexbuffer = NULL;
8293 rsurface.modelelement3i_bufferoffset = 0;
8294 rsurface.modelelement3s = (unsigned short *)element3s;
8295 rsurface.modelelement3s_indexbuffer = NULL;
8296 rsurface.modelelement3s_bufferoffset = 0;
8297 rsurface.modellightmapoffsets = NULL;
8298 rsurface.modelsurfaces = NULL;
8299 rsurface.batchgeneratedvertex = false;
8300 rsurface.batchfirstvertex = 0;
8301 rsurface.batchnumvertices = 0;
8302 rsurface.batchfirsttriangle = 0;
8303 rsurface.batchnumtriangles = 0;
8304 rsurface.batchvertex3f = NULL;
8305 rsurface.batchvertex3f_vertexbuffer = NULL;
8306 rsurface.batchvertex3f_bufferoffset = 0;
8307 rsurface.batchsvector3f = NULL;
8308 rsurface.batchsvector3f_vertexbuffer = NULL;
8309 rsurface.batchsvector3f_bufferoffset = 0;
8310 rsurface.batchtvector3f = NULL;
8311 rsurface.batchtvector3f_vertexbuffer = NULL;
8312 rsurface.batchtvector3f_bufferoffset = 0;
8313 rsurface.batchnormal3f = NULL;
8314 rsurface.batchnormal3f_vertexbuffer = NULL;
8315 rsurface.batchnormal3f_bufferoffset = 0;
8316 rsurface.batchlightmapcolor4f = NULL;
8317 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8318 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8319 rsurface.batchtexcoordtexture2f = NULL;
8320 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8321 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8322 rsurface.batchtexcoordlightmap2f = NULL;
8323 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8324 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8325 rsurface.batchvertexmesh = NULL;
8326 rsurface.batchvertexmeshbuffer = NULL;
8327 rsurface.batchvertex3fbuffer = NULL;
8328 rsurface.batchelement3i = NULL;
8329 rsurface.batchelement3i_indexbuffer = NULL;
8330 rsurface.batchelement3i_bufferoffset = 0;
8331 rsurface.batchelement3s = NULL;
8332 rsurface.batchelement3s_indexbuffer = NULL;
8333 rsurface.batchelement3s_bufferoffset = 0;
8334 rsurface.passcolor4f = NULL;
8335 rsurface.passcolor4f_vertexbuffer = NULL;
8336 rsurface.passcolor4f_bufferoffset = 0;
8338 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8340 if ((wantnormals || wanttangents) && !normal3f)
8342 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8343 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8345 if (wanttangents && !svector3f)
8347 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8348 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8349 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8354 float RSurf_FogPoint(const float *v)
8356 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8357 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8358 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8359 float FogHeightFade = r_refdef.fogheightfade;
8361 unsigned int fogmasktableindex;
8362 if (r_refdef.fogplaneviewabove)
8363 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8365 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8366 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8367 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8370 float RSurf_FogVertex(const float *v)
8372 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8373 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8374 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8375 float FogHeightFade = rsurface.fogheightfade;
8377 unsigned int fogmasktableindex;
8378 if (r_refdef.fogplaneviewabove)
8379 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8381 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8382 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8383 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8386 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8389 for (i = 0;i < numelements;i++)
8390 outelement3i[i] = inelement3i[i] + adjust;
8393 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8394 extern cvar_t gl_vbo;
8395 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8403 int surfacefirsttriangle;
8404 int surfacenumtriangles;
8405 int surfacefirstvertex;
8406 int surfaceendvertex;
8407 int surfacenumvertices;
8408 int batchnumvertices;
8409 int batchnumtriangles;
8413 qboolean dynamicvertex;
8417 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8419 q3shaderinfo_deform_t *deform;
8420 const msurface_t *surface, *firstsurface;
8421 r_vertexmesh_t *vertexmesh;
8422 if (!texturenumsurfaces)
8424 // find vertex range of this surface batch
8426 firstsurface = texturesurfacelist[0];
8427 firsttriangle = firstsurface->num_firsttriangle;
8428 batchnumvertices = 0;
8429 batchnumtriangles = 0;
8430 firstvertex = endvertex = firstsurface->num_firstvertex;
8431 for (i = 0;i < texturenumsurfaces;i++)
8433 surface = texturesurfacelist[i];
8434 if (surface != firstsurface + i)
8436 surfacefirstvertex = surface->num_firstvertex;
8437 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8438 surfacenumvertices = surface->num_vertices;
8439 surfacenumtriangles = surface->num_triangles;
8440 if (firstvertex > surfacefirstvertex)
8441 firstvertex = surfacefirstvertex;
8442 if (endvertex < surfaceendvertex)
8443 endvertex = surfaceendvertex;
8444 batchnumvertices += surfacenumvertices;
8445 batchnumtriangles += surfacenumtriangles;
8448 // we now know the vertex range used, and if there are any gaps in it
8449 rsurface.batchfirstvertex = firstvertex;
8450 rsurface.batchnumvertices = endvertex - firstvertex;
8451 rsurface.batchfirsttriangle = firsttriangle;
8452 rsurface.batchnumtriangles = batchnumtriangles;
8454 // this variable holds flags for which properties have been updated that
8455 // may require regenerating vertexmesh array...
8458 // check if any dynamic vertex processing must occur
8459 dynamicvertex = false;
8461 // if there is a chance of animated vertex colors, it's a dynamic batch
8462 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8464 dynamicvertex = true;
8465 batchneed |= BATCHNEED_NOGAPS;
8466 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8469 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8471 switch (deform->deform)
8474 case Q3DEFORM_PROJECTIONSHADOW:
8475 case Q3DEFORM_TEXT0:
8476 case Q3DEFORM_TEXT1:
8477 case Q3DEFORM_TEXT2:
8478 case Q3DEFORM_TEXT3:
8479 case Q3DEFORM_TEXT4:
8480 case Q3DEFORM_TEXT5:
8481 case Q3DEFORM_TEXT6:
8482 case Q3DEFORM_TEXT7:
8485 case Q3DEFORM_AUTOSPRITE:
8486 dynamicvertex = true;
8487 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8488 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8490 case Q3DEFORM_AUTOSPRITE2:
8491 dynamicvertex = true;
8492 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8493 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8495 case Q3DEFORM_NORMAL:
8496 dynamicvertex = true;
8497 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8498 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8501 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8502 break; // if wavefunc is a nop, ignore this transform
8503 dynamicvertex = true;
8504 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8505 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8507 case Q3DEFORM_BULGE:
8508 dynamicvertex = true;
8509 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8510 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8513 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8514 break; // if wavefunc is a nop, ignore this transform
8515 dynamicvertex = true;
8516 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8517 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8521 switch(rsurface.texture->tcgen.tcgen)
8524 case Q3TCGEN_TEXTURE:
8526 case Q3TCGEN_LIGHTMAP:
8527 dynamicvertex = true;
8528 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8529 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8531 case Q3TCGEN_VECTOR:
8532 dynamicvertex = true;
8533 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8534 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8536 case Q3TCGEN_ENVIRONMENT:
8537 dynamicvertex = true;
8538 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8539 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8542 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8544 dynamicvertex = true;
8545 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8546 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8549 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8551 dynamicvertex = true;
8552 batchneed |= BATCHNEED_NOGAPS;
8553 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8556 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8558 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8559 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8560 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8561 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8562 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8563 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8564 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8567 // when the model data has no vertex buffer (dynamic mesh), we need to
8569 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8570 batchneed |= BATCHNEED_NOGAPS;
8572 // if needsupdate, we have to do a dynamic vertex batch for sure
8573 if (needsupdate & batchneed)
8574 dynamicvertex = true;
8576 // see if we need to build vertexmesh from arrays
8577 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8578 dynamicvertex = true;
8580 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8581 // also some drivers strongly dislike firstvertex
8582 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8583 dynamicvertex = true;
8585 rsurface.batchvertex3f = rsurface.modelvertex3f;
8586 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8587 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8588 rsurface.batchsvector3f = rsurface.modelsvector3f;
8589 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8590 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8591 rsurface.batchtvector3f = rsurface.modeltvector3f;
8592 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8593 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8594 rsurface.batchnormal3f = rsurface.modelnormal3f;
8595 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8596 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8597 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8598 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8599 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8600 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8601 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8602 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8603 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8604 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8605 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8606 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8607 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8608 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8609 rsurface.batchelement3i = rsurface.modelelement3i;
8610 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8611 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8612 rsurface.batchelement3s = rsurface.modelelement3s;
8613 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8614 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8616 // if any dynamic vertex processing has to occur in software, we copy the
8617 // entire surface list together before processing to rebase the vertices
8618 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8620 // if any gaps exist and we do not have a static vertex buffer, we have to
8621 // copy the surface list together to avoid wasting upload bandwidth on the
8622 // vertices in the gaps.
8624 // if gaps exist and we have a static vertex buffer, we still have to
8625 // combine the index buffer ranges into one dynamic index buffer.
8627 // in all cases we end up with data that can be drawn in one call.
8631 // static vertex data, just set pointers...
8632 rsurface.batchgeneratedvertex = false;
8633 // if there are gaps, we want to build a combined index buffer,
8634 // otherwise use the original static buffer with an appropriate offset
8637 // build a new triangle elements array for this batch
8638 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8639 rsurface.batchfirsttriangle = 0;
8641 for (i = 0;i < texturenumsurfaces;i++)
8643 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8644 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8645 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8646 numtriangles += surfacenumtriangles;
8648 rsurface.batchelement3i_indexbuffer = NULL;
8649 rsurface.batchelement3i_bufferoffset = 0;
8650 rsurface.batchelement3s = NULL;
8651 rsurface.batchelement3s_indexbuffer = NULL;
8652 rsurface.batchelement3s_bufferoffset = 0;
8653 if (endvertex <= 65536)
8655 // make a 16bit (unsigned short) index array if possible
8656 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8657 for (i = 0;i < numtriangles*3;i++)
8658 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8664 // something needs software processing, do it for real...
8665 // we only directly handle separate array data in this case and then
8666 // generate interleaved data if needed...
8667 rsurface.batchgeneratedvertex = true;
8669 // now copy the vertex data into a combined array and make an index array
8670 // (this is what Quake3 does all the time)
8671 //if (gaps || rsurface.batchfirstvertex)
8673 rsurface.batchvertex3fbuffer = NULL;
8674 rsurface.batchvertexmesh = NULL;
8675 rsurface.batchvertexmeshbuffer = NULL;
8676 rsurface.batchvertex3f = NULL;
8677 rsurface.batchvertex3f_vertexbuffer = NULL;
8678 rsurface.batchvertex3f_bufferoffset = 0;
8679 rsurface.batchsvector3f = NULL;
8680 rsurface.batchsvector3f_vertexbuffer = NULL;
8681 rsurface.batchsvector3f_bufferoffset = 0;
8682 rsurface.batchtvector3f = NULL;
8683 rsurface.batchtvector3f_vertexbuffer = NULL;
8684 rsurface.batchtvector3f_bufferoffset = 0;
8685 rsurface.batchnormal3f = NULL;
8686 rsurface.batchnormal3f_vertexbuffer = NULL;
8687 rsurface.batchnormal3f_bufferoffset = 0;
8688 rsurface.batchlightmapcolor4f = NULL;
8689 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8690 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8691 rsurface.batchtexcoordtexture2f = NULL;
8692 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8693 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8694 rsurface.batchtexcoordlightmap2f = NULL;
8695 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8696 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8697 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8698 rsurface.batchelement3i_indexbuffer = NULL;
8699 rsurface.batchelement3i_bufferoffset = 0;
8700 rsurface.batchelement3s = NULL;
8701 rsurface.batchelement3s_indexbuffer = NULL;
8702 rsurface.batchelement3s_bufferoffset = 0;
8703 // we'll only be setting up certain arrays as needed
8704 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8705 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8706 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8707 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8708 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8709 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8710 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8712 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8713 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8715 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8716 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8717 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8718 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8719 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8720 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8723 for (i = 0;i < texturenumsurfaces;i++)
8725 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8726 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8727 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8728 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8729 // copy only the data requested
8730 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8731 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8732 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8734 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8736 if (rsurface.batchvertex3f)
8737 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8739 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8741 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8743 if (rsurface.modelnormal3f)
8744 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8746 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8748 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8750 if (rsurface.modelsvector3f)
8752 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8753 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8757 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8758 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8761 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8763 if (rsurface.modellightmapcolor4f)
8764 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8766 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8768 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8770 if (rsurface.modeltexcoordtexture2f)
8771 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8773 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8775 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8777 if (rsurface.modeltexcoordlightmap2f)
8778 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8780 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8783 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8784 numvertices += surfacenumvertices;
8785 numtriangles += surfacenumtriangles;
8788 // generate a 16bit index array as well if possible
8789 // (in general, dynamic batches fit)
8790 if (numvertices <= 65536)
8792 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8793 for (i = 0;i < numtriangles*3;i++)
8794 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8797 // since we've copied everything, the batch now starts at 0
8798 rsurface.batchfirstvertex = 0;
8799 rsurface.batchnumvertices = batchnumvertices;
8800 rsurface.batchfirsttriangle = 0;
8801 rsurface.batchnumtriangles = batchnumtriangles;
8804 // q1bsp surfaces rendered in vertex color mode have to have colors
8805 // calculated based on lightstyles
8806 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8808 // generate color arrays for the surfaces in this list
8813 const unsigned char *lm;
8814 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8815 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8816 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8818 for (i = 0;i < texturenumsurfaces;i++)
8820 surface = texturesurfacelist[i];
8821 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8822 surfacenumvertices = surface->num_vertices;
8823 if (surface->lightmapinfo->samples)
8825 for (j = 0;j < surfacenumvertices;j++)
8827 lm = surface->lightmapinfo->samples + offsets[j];
8828 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8829 VectorScale(lm, scale, c);
8830 if (surface->lightmapinfo->styles[1] != 255)
8832 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8834 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8835 VectorMA(c, scale, lm, c);
8836 if (surface->lightmapinfo->styles[2] != 255)
8839 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8840 VectorMA(c, scale, lm, c);
8841 if (surface->lightmapinfo->styles[3] != 255)
8844 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8845 VectorMA(c, scale, lm, c);
8852 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);
8858 for (j = 0;j < surfacenumvertices;j++)
8860 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8867 // if vertices are deformed (sprite flares and things in maps, possibly
8868 // water waves, bulges and other deformations), modify the copied vertices
8870 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8872 switch (deform->deform)
8875 case Q3DEFORM_PROJECTIONSHADOW:
8876 case Q3DEFORM_TEXT0:
8877 case Q3DEFORM_TEXT1:
8878 case Q3DEFORM_TEXT2:
8879 case Q3DEFORM_TEXT3:
8880 case Q3DEFORM_TEXT4:
8881 case Q3DEFORM_TEXT5:
8882 case Q3DEFORM_TEXT6:
8883 case Q3DEFORM_TEXT7:
8886 case Q3DEFORM_AUTOSPRITE:
8887 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8888 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8889 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8890 VectorNormalize(newforward);
8891 VectorNormalize(newright);
8892 VectorNormalize(newup);
8893 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8894 // rsurface.batchvertex3f_vertexbuffer = NULL;
8895 // rsurface.batchvertex3f_bufferoffset = 0;
8896 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8897 // rsurface.batchsvector3f_vertexbuffer = NULL;
8898 // rsurface.batchsvector3f_bufferoffset = 0;
8899 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8900 // rsurface.batchtvector3f_vertexbuffer = NULL;
8901 // rsurface.batchtvector3f_bufferoffset = 0;
8902 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8903 // rsurface.batchnormal3f_vertexbuffer = NULL;
8904 // rsurface.batchnormal3f_bufferoffset = 0;
8905 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8906 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8907 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8908 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8909 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);
8910 // a single autosprite surface can contain multiple sprites...
8911 for (j = 0;j < batchnumvertices - 3;j += 4)
8913 VectorClear(center);
8914 for (i = 0;i < 4;i++)
8915 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8916 VectorScale(center, 0.25f, center);
8917 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8918 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8919 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8920 for (i = 0;i < 4;i++)
8922 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8923 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8926 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8927 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8928 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);
8930 case Q3DEFORM_AUTOSPRITE2:
8931 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8932 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8933 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8934 VectorNormalize(newforward);
8935 VectorNormalize(newright);
8936 VectorNormalize(newup);
8937 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8938 // rsurface.batchvertex3f_vertexbuffer = NULL;
8939 // rsurface.batchvertex3f_bufferoffset = 0;
8941 const float *v1, *v2;
8951 memset(shortest, 0, sizeof(shortest));
8952 // a single autosprite surface can contain multiple sprites...
8953 for (j = 0;j < batchnumvertices - 3;j += 4)
8955 VectorClear(center);
8956 for (i = 0;i < 4;i++)
8957 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8958 VectorScale(center, 0.25f, center);
8959 // find the two shortest edges, then use them to define the
8960 // axis vectors for rotating around the central axis
8961 for (i = 0;i < 6;i++)
8963 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8964 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8965 l = VectorDistance2(v1, v2);
8966 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8968 l += (1.0f / 1024.0f);
8969 if (shortest[0].length2 > l || i == 0)
8971 shortest[1] = shortest[0];
8972 shortest[0].length2 = l;
8973 shortest[0].v1 = v1;
8974 shortest[0].v2 = v2;
8976 else if (shortest[1].length2 > l || i == 1)
8978 shortest[1].length2 = l;
8979 shortest[1].v1 = v1;
8980 shortest[1].v2 = v2;
8983 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8984 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8985 // this calculates the right vector from the shortest edge
8986 // and the up vector from the edge midpoints
8987 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8988 VectorNormalize(right);
8989 VectorSubtract(end, start, up);
8990 VectorNormalize(up);
8991 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8992 VectorSubtract(rsurface.localvieworigin, center, forward);
8993 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8994 VectorNegate(forward, forward);
8995 VectorReflect(forward, 0, up, forward);
8996 VectorNormalize(forward);
8997 CrossProduct(up, forward, newright);
8998 VectorNormalize(newright);
8999 // rotate the quad around the up axis vector, this is made
9000 // especially easy by the fact we know the quad is flat,
9001 // so we only have to subtract the center position and
9002 // measure distance along the right vector, and then
9003 // multiply that by the newright vector and add back the
9005 // we also need to subtract the old position to undo the
9006 // displacement from the center, which we do with a
9007 // DotProduct, the subtraction/addition of center is also
9008 // optimized into DotProducts here
9009 l = DotProduct(right, center);
9010 for (i = 0;i < 4;i++)
9012 v1 = rsurface.batchvertex3f + 3*(j+i);
9013 f = DotProduct(right, v1) - l;
9014 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9018 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9020 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9021 // rsurface.batchnormal3f_vertexbuffer = NULL;
9022 // rsurface.batchnormal3f_bufferoffset = 0;
9023 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9025 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9027 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9028 // rsurface.batchsvector3f_vertexbuffer = NULL;
9029 // rsurface.batchsvector3f_bufferoffset = 0;
9030 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9031 // rsurface.batchtvector3f_vertexbuffer = NULL;
9032 // rsurface.batchtvector3f_bufferoffset = 0;
9033 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);
9036 case Q3DEFORM_NORMAL:
9037 // deform the normals to make reflections wavey
9038 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9039 rsurface.batchnormal3f_vertexbuffer = NULL;
9040 rsurface.batchnormal3f_bufferoffset = 0;
9041 for (j = 0;j < batchnumvertices;j++)
9044 float *normal = rsurface.batchnormal3f + 3*j;
9045 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9046 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9047 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9048 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9049 VectorNormalize(normal);
9051 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9053 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9054 // rsurface.batchsvector3f_vertexbuffer = NULL;
9055 // rsurface.batchsvector3f_bufferoffset = 0;
9056 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9057 // rsurface.batchtvector3f_vertexbuffer = NULL;
9058 // rsurface.batchtvector3f_bufferoffset = 0;
9059 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);
9063 // deform vertex array to make wavey water and flags and such
9064 waveparms[0] = deform->waveparms[0];
9065 waveparms[1] = deform->waveparms[1];
9066 waveparms[2] = deform->waveparms[2];
9067 waveparms[3] = deform->waveparms[3];
9068 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9069 break; // if wavefunc is a nop, don't make a dynamic vertex array
9070 // this is how a divisor of vertex influence on deformation
9071 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9072 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9073 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9074 // rsurface.batchvertex3f_vertexbuffer = NULL;
9075 // rsurface.batchvertex3f_bufferoffset = 0;
9076 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9077 // rsurface.batchnormal3f_vertexbuffer = NULL;
9078 // rsurface.batchnormal3f_bufferoffset = 0;
9079 for (j = 0;j < batchnumvertices;j++)
9081 // if the wavefunc depends on time, evaluate it per-vertex
9084 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9085 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9087 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9089 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9090 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9091 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9093 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9094 // rsurface.batchsvector3f_vertexbuffer = NULL;
9095 // rsurface.batchsvector3f_bufferoffset = 0;
9096 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9097 // rsurface.batchtvector3f_vertexbuffer = NULL;
9098 // rsurface.batchtvector3f_bufferoffset = 0;
9099 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);
9102 case Q3DEFORM_BULGE:
9103 // deform vertex array to make the surface have moving bulges
9104 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9105 // rsurface.batchvertex3f_vertexbuffer = NULL;
9106 // rsurface.batchvertex3f_bufferoffset = 0;
9107 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9108 // rsurface.batchnormal3f_vertexbuffer = NULL;
9109 // rsurface.batchnormal3f_bufferoffset = 0;
9110 for (j = 0;j < batchnumvertices;j++)
9112 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9113 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9115 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9116 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9117 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9119 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9120 // rsurface.batchsvector3f_vertexbuffer = NULL;
9121 // rsurface.batchsvector3f_bufferoffset = 0;
9122 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9123 // rsurface.batchtvector3f_vertexbuffer = NULL;
9124 // rsurface.batchtvector3f_bufferoffset = 0;
9125 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);
9129 // deform vertex array
9130 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9131 break; // if wavefunc is a nop, don't make a dynamic vertex array
9132 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9133 VectorScale(deform->parms, scale, waveparms);
9134 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9135 // rsurface.batchvertex3f_vertexbuffer = NULL;
9136 // rsurface.batchvertex3f_bufferoffset = 0;
9137 for (j = 0;j < batchnumvertices;j++)
9138 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9143 // generate texcoords based on the chosen texcoord source
9144 switch(rsurface.texture->tcgen.tcgen)
9147 case Q3TCGEN_TEXTURE:
9149 case Q3TCGEN_LIGHTMAP:
9150 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9151 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9152 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9153 if (rsurface.batchtexcoordlightmap2f)
9154 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9156 case Q3TCGEN_VECTOR:
9157 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9158 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9159 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9160 for (j = 0;j < batchnumvertices;j++)
9162 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9163 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9166 case Q3TCGEN_ENVIRONMENT:
9167 // make environment reflections using a spheremap
9168 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9169 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9170 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9171 for (j = 0;j < batchnumvertices;j++)
9173 // identical to Q3A's method, but executed in worldspace so
9174 // carried models can be shiny too
9176 float viewer[3], d, reflected[3], worldreflected[3];
9178 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9179 // VectorNormalize(viewer);
9181 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9183 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9184 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9185 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9186 // note: this is proportinal to viewer, so we can normalize later
9188 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9189 VectorNormalize(worldreflected);
9191 // note: this sphere map only uses world x and z!
9192 // so positive and negative y will LOOK THE SAME.
9193 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9194 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9198 // the only tcmod that needs software vertex processing is turbulent, so
9199 // check for it here and apply the changes if needed
9200 // and we only support that as the first one
9201 // (handling a mixture of turbulent and other tcmods would be problematic
9202 // without punting it entirely to a software path)
9203 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9205 amplitude = rsurface.texture->tcmods[0].parms[1];
9206 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9207 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9208 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9209 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9210 for (j = 0;j < batchnumvertices;j++)
9212 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);
9213 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9217 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9219 // convert the modified arrays to vertex structs
9220 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9221 // rsurface.batchvertexmeshbuffer = NULL;
9222 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9223 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9224 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9225 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9226 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9227 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9228 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9230 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9232 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9233 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9236 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9237 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9238 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9239 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9240 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9241 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9242 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9243 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9244 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9248 void RSurf_DrawBatch(void)
9250 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9251 // through the pipeline, killing it earlier in the pipeline would have
9252 // per-surface overhead rather than per-batch overhead, so it's best to
9253 // reject it here, before it hits glDraw.
9254 if (rsurface.batchnumtriangles == 0)
9257 // batch debugging code
9258 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9264 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9265 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9268 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9270 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9272 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9273 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);
9280 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);
9283 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9285 // pick the closest matching water plane
9286 int planeindex, vertexindex, bestplaneindex = -1;
9290 r_waterstate_waterplane_t *p;
9291 qboolean prepared = false;
9293 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9295 if(p->camera_entity != rsurface.texture->camera_entity)
9300 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9302 if(rsurface.batchnumvertices == 0)
9305 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9307 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9308 d += fabs(PlaneDiff(vert, &p->plane));
9310 if (bestd > d || bestplaneindex < 0)
9313 bestplaneindex = planeindex;
9316 return bestplaneindex;
9317 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9318 // this situation though, as it might be better to render single larger
9319 // batches with useless stuff (backface culled for example) than to
9320 // render multiple smaller batches
9323 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9326 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9327 rsurface.passcolor4f_vertexbuffer = 0;
9328 rsurface.passcolor4f_bufferoffset = 0;
9329 for (i = 0;i < rsurface.batchnumvertices;i++)
9330 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9333 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9340 if (rsurface.passcolor4f)
9342 // generate color arrays
9343 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9344 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9345 rsurface.passcolor4f_vertexbuffer = 0;
9346 rsurface.passcolor4f_bufferoffset = 0;
9347 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)
9349 f = RSurf_FogVertex(v);
9358 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9359 rsurface.passcolor4f_vertexbuffer = 0;
9360 rsurface.passcolor4f_bufferoffset = 0;
9361 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9363 f = RSurf_FogVertex(v);
9372 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9379 if (!rsurface.passcolor4f)
9381 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9382 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9383 rsurface.passcolor4f_vertexbuffer = 0;
9384 rsurface.passcolor4f_bufferoffset = 0;
9385 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)
9387 f = RSurf_FogVertex(v);
9388 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9389 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9390 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9395 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9400 if (!rsurface.passcolor4f)
9402 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9403 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9404 rsurface.passcolor4f_vertexbuffer = 0;
9405 rsurface.passcolor4f_bufferoffset = 0;
9406 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9415 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9420 if (!rsurface.passcolor4f)
9422 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9423 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9424 rsurface.passcolor4f_vertexbuffer = 0;
9425 rsurface.passcolor4f_bufferoffset = 0;
9426 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9428 c2[0] = c[0] + r_refdef.scene.ambient;
9429 c2[1] = c[1] + r_refdef.scene.ambient;
9430 c2[2] = c[2] + r_refdef.scene.ambient;
9435 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9438 rsurface.passcolor4f = NULL;
9439 rsurface.passcolor4f_vertexbuffer = 0;
9440 rsurface.passcolor4f_bufferoffset = 0;
9441 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9442 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9443 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9444 GL_Color(r, g, b, a);
9445 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9449 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9451 // TODO: optimize applyfog && applycolor case
9452 // just apply fog if necessary, and tint the fog color array if necessary
9453 rsurface.passcolor4f = NULL;
9454 rsurface.passcolor4f_vertexbuffer = 0;
9455 rsurface.passcolor4f_bufferoffset = 0;
9456 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9457 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9458 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9459 GL_Color(r, g, b, a);
9463 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9466 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9467 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9468 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9469 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9470 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9471 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9472 GL_Color(r, g, b, a);
9476 static void RSurf_DrawBatch_GL11_ClampColor(void)
9481 if (!rsurface.passcolor4f)
9483 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9485 c2[0] = bound(0.0f, c1[0], 1.0f);
9486 c2[1] = bound(0.0f, c1[1], 1.0f);
9487 c2[2] = bound(0.0f, c1[2], 1.0f);
9488 c2[3] = bound(0.0f, c1[3], 1.0f);
9492 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9502 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9503 rsurface.passcolor4f_vertexbuffer = 0;
9504 rsurface.passcolor4f_bufferoffset = 0;
9505 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)
9507 f = -DotProduct(r_refdef.view.forward, n);
9509 f = f * 0.85 + 0.15; // work around so stuff won't get black
9510 f *= r_refdef.lightmapintensity;
9511 Vector4Set(c, f, f, f, 1);
9515 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9517 RSurf_DrawBatch_GL11_ApplyFakeLight();
9518 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9519 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9520 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9521 GL_Color(r, g, b, a);
9525 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9533 vec3_t ambientcolor;
9534 vec3_t diffusecolor;
9538 VectorCopy(rsurface.modellight_lightdir, lightdir);
9539 f = 0.5f * r_refdef.lightmapintensity;
9540 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9541 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9542 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9543 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9544 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9545 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9547 if (VectorLength2(diffusecolor) > 0)
9549 // q3-style directional shading
9550 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9551 rsurface.passcolor4f_vertexbuffer = 0;
9552 rsurface.passcolor4f_bufferoffset = 0;
9553 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)
9555 if ((f = DotProduct(n, lightdir)) > 0)
9556 VectorMA(ambientcolor, f, diffusecolor, c);
9558 VectorCopy(ambientcolor, c);
9565 *applycolor = false;
9569 *r = ambientcolor[0];
9570 *g = ambientcolor[1];
9571 *b = ambientcolor[2];
9572 rsurface.passcolor4f = NULL;
9573 rsurface.passcolor4f_vertexbuffer = 0;
9574 rsurface.passcolor4f_bufferoffset = 0;
9578 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9580 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9581 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9582 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9583 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9584 GL_Color(r, g, b, a);
9588 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9596 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9597 rsurface.passcolor4f_vertexbuffer = 0;
9598 rsurface.passcolor4f_bufferoffset = 0;
9600 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9602 f = 1 - RSurf_FogVertex(v);
9610 void RSurf_SetupDepthAndCulling(void)
9612 // submodels are biased to avoid z-fighting with world surfaces that they
9613 // may be exactly overlapping (avoids z-fighting artifacts on certain
9614 // doors and things in Quake maps)
9615 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9616 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9617 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9618 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9621 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9623 // transparent sky would be ridiculous
9624 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9626 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9627 skyrenderlater = true;
9628 RSurf_SetupDepthAndCulling();
9630 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9631 // skymasking on them, and Quake3 never did sky masking (unlike
9632 // software Quake and software Quake2), so disable the sky masking
9633 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9634 // and skymasking also looks very bad when noclipping outside the
9635 // level, so don't use it then either.
9636 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9638 R_Mesh_ResetTextureState();
9639 if (skyrendermasked)
9641 R_SetupShader_DepthOrShadow(false);
9642 // depth-only (masking)
9643 GL_ColorMask(0,0,0,0);
9644 // just to make sure that braindead drivers don't draw
9645 // anything despite that colormask...
9646 GL_BlendFunc(GL_ZERO, GL_ONE);
9647 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9648 if (rsurface.batchvertex3fbuffer)
9649 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9651 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9655 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9657 GL_BlendFunc(GL_ONE, GL_ZERO);
9658 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9659 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9660 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9663 if (skyrendermasked)
9664 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9666 R_Mesh_ResetTextureState();
9667 GL_Color(1, 1, 1, 1);
9670 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9671 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9672 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9674 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9678 // render screenspace normalmap to texture
9680 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9684 // bind lightmap texture
9686 // water/refraction/reflection/camera surfaces have to be handled specially
9687 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9689 int start, end, startplaneindex;
9690 for (start = 0;start < texturenumsurfaces;start = end)
9692 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9693 if(startplaneindex < 0)
9695 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9696 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9700 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9702 // now that we have a batch using the same planeindex, render it
9703 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9705 // render water or distortion background
9707 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);
9709 // blend surface on top
9710 GL_DepthMask(false);
9711 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9714 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9716 // render surface with reflection texture as input
9717 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9718 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);
9725 // render surface batch normally
9726 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9727 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);
9731 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9733 // OpenGL 1.3 path - anything not completely ancient
9734 qboolean applycolor;
9737 const texturelayer_t *layer;
9738 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);
9739 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9741 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9744 int layertexrgbscale;
9745 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9747 if (layerindex == 0)
9751 GL_AlphaTest(false);
9752 GL_DepthFunc(GL_EQUAL);
9755 GL_DepthMask(layer->depthmask && writedepth);
9756 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9757 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9759 layertexrgbscale = 4;
9760 VectorScale(layer->color, 0.25f, layercolor);
9762 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9764 layertexrgbscale = 2;
9765 VectorScale(layer->color, 0.5f, layercolor);
9769 layertexrgbscale = 1;
9770 VectorScale(layer->color, 1.0f, layercolor);
9772 layercolor[3] = layer->color[3];
9773 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9774 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9775 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9776 switch (layer->type)
9778 case TEXTURELAYERTYPE_LITTEXTURE:
9779 // single-pass lightmapped texture with 2x rgbscale
9780 R_Mesh_TexBind(0, r_texture_white);
9781 R_Mesh_TexMatrix(0, NULL);
9782 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9783 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9784 R_Mesh_TexBind(1, layer->texture);
9785 R_Mesh_TexMatrix(1, &layer->texmatrix);
9786 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9787 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9788 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9789 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9790 else if (FAKELIGHT_ENABLED)
9791 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9792 else if (rsurface.uselightmaptexture)
9793 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9795 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9797 case TEXTURELAYERTYPE_TEXTURE:
9798 // singletexture unlit texture with transparency support
9799 R_Mesh_TexBind(0, layer->texture);
9800 R_Mesh_TexMatrix(0, &layer->texmatrix);
9801 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9802 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9803 R_Mesh_TexBind(1, 0);
9804 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9805 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9807 case TEXTURELAYERTYPE_FOG:
9808 // singletexture fogging
9811 R_Mesh_TexBind(0, layer->texture);
9812 R_Mesh_TexMatrix(0, &layer->texmatrix);
9813 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9814 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9818 R_Mesh_TexBind(0, 0);
9819 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9821 R_Mesh_TexBind(1, 0);
9822 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9823 // generate a color array for the fog pass
9824 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9825 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9829 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9832 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9834 GL_DepthFunc(GL_LEQUAL);
9835 GL_AlphaTest(false);
9839 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9841 // OpenGL 1.1 - crusty old voodoo path
9844 const texturelayer_t *layer;
9845 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9846 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9848 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9850 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9852 if (layerindex == 0)
9856 GL_AlphaTest(false);
9857 GL_DepthFunc(GL_EQUAL);
9860 GL_DepthMask(layer->depthmask && writedepth);
9861 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9862 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9863 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9864 switch (layer->type)
9866 case TEXTURELAYERTYPE_LITTEXTURE:
9867 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9869 // two-pass lit texture with 2x rgbscale
9870 // first the lightmap pass
9871 R_Mesh_TexBind(0, r_texture_white);
9872 R_Mesh_TexMatrix(0, NULL);
9873 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9874 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9875 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9876 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9877 else if (FAKELIGHT_ENABLED)
9878 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9879 else if (rsurface.uselightmaptexture)
9880 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9882 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9883 // then apply the texture to it
9884 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9885 R_Mesh_TexBind(0, layer->texture);
9886 R_Mesh_TexMatrix(0, &layer->texmatrix);
9887 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9888 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9889 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);
9893 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9894 R_Mesh_TexBind(0, layer->texture);
9895 R_Mesh_TexMatrix(0, &layer->texmatrix);
9896 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9897 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9898 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9899 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);
9901 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);
9904 case TEXTURELAYERTYPE_TEXTURE:
9905 // singletexture unlit texture with transparency support
9906 R_Mesh_TexBind(0, layer->texture);
9907 R_Mesh_TexMatrix(0, &layer->texmatrix);
9908 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9909 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9910 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);
9912 case TEXTURELAYERTYPE_FOG:
9913 // singletexture fogging
9916 R_Mesh_TexBind(0, layer->texture);
9917 R_Mesh_TexMatrix(0, &layer->texmatrix);
9918 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9919 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9923 R_Mesh_TexBind(0, 0);
9924 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9926 // generate a color array for the fog pass
9927 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9928 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9932 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9935 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9937 GL_DepthFunc(GL_LEQUAL);
9938 GL_AlphaTest(false);
9942 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9946 r_vertexgeneric_t *batchvertex;
9949 // R_Mesh_ResetTextureState();
9950 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9952 if(rsurface.texture && rsurface.texture->currentskinframe)
9954 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9955 c[3] *= rsurface.texture->currentalpha;
9965 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9967 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9968 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9969 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9972 // brighten it up (as texture value 127 means "unlit")
9973 c[0] *= 2 * r_refdef.view.colorscale;
9974 c[1] *= 2 * r_refdef.view.colorscale;
9975 c[2] *= 2 * r_refdef.view.colorscale;
9977 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9978 c[3] *= r_wateralpha.value;
9980 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9982 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9983 GL_DepthMask(false);
9985 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9987 GL_BlendFunc(GL_ONE, GL_ONE);
9988 GL_DepthMask(false);
9990 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9992 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9993 GL_DepthMask(false);
9995 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9997 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9998 GL_DepthMask(false);
10002 GL_BlendFunc(GL_ONE, GL_ZERO);
10003 GL_DepthMask(writedepth);
10006 if (r_showsurfaces.integer == 3)
10008 rsurface.passcolor4f = NULL;
10010 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10012 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10014 rsurface.passcolor4f = NULL;
10015 rsurface.passcolor4f_vertexbuffer = 0;
10016 rsurface.passcolor4f_bufferoffset = 0;
10018 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10020 qboolean applycolor = true;
10023 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10025 r_refdef.lightmapintensity = 1;
10026 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10027 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10029 else if (FAKELIGHT_ENABLED)
10031 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10033 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10034 RSurf_DrawBatch_GL11_ApplyFakeLight();
10035 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10039 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10041 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10042 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10043 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10046 if(!rsurface.passcolor4f)
10047 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10049 RSurf_DrawBatch_GL11_ApplyAmbient();
10050 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10051 if(r_refdef.fogenabled)
10052 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10053 RSurf_DrawBatch_GL11_ClampColor();
10055 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10056 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10059 else if (!r_refdef.view.showdebug)
10061 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10062 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10063 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10065 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10066 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10068 R_Mesh_PrepareVertices_Generic_Unlock();
10071 else if (r_showsurfaces.integer == 4)
10073 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10074 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10075 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10077 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10078 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10079 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10081 R_Mesh_PrepareVertices_Generic_Unlock();
10084 else if (r_showsurfaces.integer == 2)
10087 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10088 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10089 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10091 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10092 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10093 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10094 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10095 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10096 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10097 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10099 R_Mesh_PrepareVertices_Generic_Unlock();
10100 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10104 int texturesurfaceindex;
10106 const msurface_t *surface;
10107 float surfacecolor4f[4];
10108 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10109 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10111 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10113 surface = texturesurfacelist[texturesurfaceindex];
10114 k = (int)(((size_t)surface) / sizeof(msurface_t));
10115 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10116 for (j = 0;j < surface->num_vertices;j++)
10118 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10119 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10123 R_Mesh_PrepareVertices_Generic_Unlock();
10128 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10131 RSurf_SetupDepthAndCulling();
10132 if (r_showsurfaces.integer)
10134 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10137 switch (vid.renderpath)
10139 case RENDERPATH_GL20:
10140 case RENDERPATH_D3D9:
10141 case RENDERPATH_D3D10:
10142 case RENDERPATH_D3D11:
10143 case RENDERPATH_SOFT:
10144 case RENDERPATH_GLES2:
10145 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10147 case RENDERPATH_GL13:
10148 case RENDERPATH_GLES1:
10149 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10151 case RENDERPATH_GL11:
10152 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10158 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10161 RSurf_SetupDepthAndCulling();
10162 if (r_showsurfaces.integer)
10164 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10167 switch (vid.renderpath)
10169 case RENDERPATH_GL20:
10170 case RENDERPATH_D3D9:
10171 case RENDERPATH_D3D10:
10172 case RENDERPATH_D3D11:
10173 case RENDERPATH_SOFT:
10174 case RENDERPATH_GLES2:
10175 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10177 case RENDERPATH_GL13:
10178 case RENDERPATH_GLES1:
10179 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10181 case RENDERPATH_GL11:
10182 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10188 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10191 int texturenumsurfaces, endsurface;
10192 texture_t *texture;
10193 const msurface_t *surface;
10194 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10196 // if the model is static it doesn't matter what value we give for
10197 // wantnormals and wanttangents, so this logic uses only rules applicable
10198 // to a model, knowing that they are meaningless otherwise
10199 if (ent == r_refdef.scene.worldentity)
10200 RSurf_ActiveWorldEntity();
10201 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10202 RSurf_ActiveModelEntity(ent, false, false, false);
10205 switch (vid.renderpath)
10207 case RENDERPATH_GL20:
10208 case RENDERPATH_D3D9:
10209 case RENDERPATH_D3D10:
10210 case RENDERPATH_D3D11:
10211 case RENDERPATH_SOFT:
10212 case RENDERPATH_GLES2:
10213 RSurf_ActiveModelEntity(ent, true, true, false);
10215 case RENDERPATH_GL11:
10216 case RENDERPATH_GL13:
10217 case RENDERPATH_GLES1:
10218 RSurf_ActiveModelEntity(ent, true, false, false);
10223 if (r_transparentdepthmasking.integer)
10225 qboolean setup = false;
10226 for (i = 0;i < numsurfaces;i = j)
10229 surface = rsurface.modelsurfaces + surfacelist[i];
10230 texture = surface->texture;
10231 rsurface.texture = R_GetCurrentTexture(texture);
10232 rsurface.lightmaptexture = NULL;
10233 rsurface.deluxemaptexture = NULL;
10234 rsurface.uselightmaptexture = false;
10235 // scan ahead until we find a different texture
10236 endsurface = min(i + 1024, numsurfaces);
10237 texturenumsurfaces = 0;
10238 texturesurfacelist[texturenumsurfaces++] = surface;
10239 for (;j < endsurface;j++)
10241 surface = rsurface.modelsurfaces + surfacelist[j];
10242 if (texture != surface->texture)
10244 texturesurfacelist[texturenumsurfaces++] = surface;
10246 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10248 // render the range of surfaces as depth
10252 GL_ColorMask(0,0,0,0);
10254 GL_DepthTest(true);
10255 GL_BlendFunc(GL_ONE, GL_ZERO);
10256 GL_DepthMask(true);
10257 // R_Mesh_ResetTextureState();
10258 R_SetupShader_DepthOrShadow(false);
10260 RSurf_SetupDepthAndCulling();
10261 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10262 if (rsurface.batchvertex3fbuffer)
10263 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10265 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10269 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10272 for (i = 0;i < numsurfaces;i = j)
10275 surface = rsurface.modelsurfaces + surfacelist[i];
10276 texture = surface->texture;
10277 rsurface.texture = R_GetCurrentTexture(texture);
10278 // scan ahead until we find a different texture
10279 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10280 texturenumsurfaces = 0;
10281 texturesurfacelist[texturenumsurfaces++] = surface;
10282 if(FAKELIGHT_ENABLED)
10284 rsurface.lightmaptexture = NULL;
10285 rsurface.deluxemaptexture = NULL;
10286 rsurface.uselightmaptexture = false;
10287 for (;j < endsurface;j++)
10289 surface = rsurface.modelsurfaces + surfacelist[j];
10290 if (texture != surface->texture)
10292 texturesurfacelist[texturenumsurfaces++] = surface;
10297 rsurface.lightmaptexture = surface->lightmaptexture;
10298 rsurface.deluxemaptexture = surface->deluxemaptexture;
10299 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10300 for (;j < endsurface;j++)
10302 surface = rsurface.modelsurfaces + surfacelist[j];
10303 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10305 texturesurfacelist[texturenumsurfaces++] = surface;
10308 // render the range of surfaces
10309 if (ent == r_refdef.scene.worldentity)
10310 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10312 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10314 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10317 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10319 // transparent surfaces get pushed off into the transparent queue
10320 int surfacelistindex;
10321 const msurface_t *surface;
10322 vec3_t tempcenter, center;
10323 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10325 surface = texturesurfacelist[surfacelistindex];
10326 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10327 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10328 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10329 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10330 if (queueentity->transparent_offset) // transparent offset
10332 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10333 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10334 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10336 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10340 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10342 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10344 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10346 RSurf_SetupDepthAndCulling();
10347 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10348 if (rsurface.batchvertex3fbuffer)
10349 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10351 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10355 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10357 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10360 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10363 if (!rsurface.texture->currentnumlayers)
10365 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10366 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10368 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10370 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10371 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10372 else if (!rsurface.texture->currentnumlayers)
10374 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10376 // in the deferred case, transparent surfaces were queued during prepass
10377 if (!r_shadow_usingdeferredprepass)
10378 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10382 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10383 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10388 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10391 texture_t *texture;
10392 R_FrameData_SetMark();
10393 // break the surface list down into batches by texture and use of lightmapping
10394 for (i = 0;i < numsurfaces;i = j)
10397 // texture is the base texture pointer, rsurface.texture is the
10398 // current frame/skin the texture is directing us to use (for example
10399 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10400 // use skin 1 instead)
10401 texture = surfacelist[i]->texture;
10402 rsurface.texture = R_GetCurrentTexture(texture);
10403 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10405 // if this texture is not the kind we want, skip ahead to the next one
10406 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10410 if(FAKELIGHT_ENABLED || depthonly || prepass)
10412 rsurface.lightmaptexture = NULL;
10413 rsurface.deluxemaptexture = NULL;
10414 rsurface.uselightmaptexture = false;
10415 // simply scan ahead until we find a different texture or lightmap state
10416 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10421 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10422 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10423 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10424 // simply scan ahead until we find a different texture or lightmap state
10425 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10428 // render the range of surfaces
10429 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10431 R_FrameData_ReturnToMark();
10434 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10438 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10441 if (!rsurface.texture->currentnumlayers)
10443 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10444 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10446 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10448 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10449 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10450 else if (!rsurface.texture->currentnumlayers)
10452 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10454 // in the deferred case, transparent surfaces were queued during prepass
10455 if (!r_shadow_usingdeferredprepass)
10456 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10460 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10461 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10466 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10469 texture_t *texture;
10470 R_FrameData_SetMark();
10471 // break the surface list down into batches by texture and use of lightmapping
10472 for (i = 0;i < numsurfaces;i = j)
10475 // texture is the base texture pointer, rsurface.texture is the
10476 // current frame/skin the texture is directing us to use (for example
10477 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10478 // use skin 1 instead)
10479 texture = surfacelist[i]->texture;
10480 rsurface.texture = R_GetCurrentTexture(texture);
10481 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10483 // if this texture is not the kind we want, skip ahead to the next one
10484 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10488 if(FAKELIGHT_ENABLED || depthonly || prepass)
10490 rsurface.lightmaptexture = NULL;
10491 rsurface.deluxemaptexture = NULL;
10492 rsurface.uselightmaptexture = false;
10493 // simply scan ahead until we find a different texture or lightmap state
10494 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10499 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10500 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10501 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10502 // simply scan ahead until we find a different texture or lightmap state
10503 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10506 // render the range of surfaces
10507 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10509 R_FrameData_ReturnToMark();
10512 float locboxvertex3f[6*4*3] =
10514 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10515 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10516 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10517 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10518 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10519 1,0,0, 0,0,0, 0,1,0, 1,1,0
10522 unsigned short locboxelements[6*2*3] =
10527 12,13,14, 12,14,15,
10528 16,17,18, 16,18,19,
10532 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10535 cl_locnode_t *loc = (cl_locnode_t *)ent;
10537 float vertex3f[6*4*3];
10539 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10540 GL_DepthMask(false);
10541 GL_DepthRange(0, 1);
10542 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10543 GL_DepthTest(true);
10544 GL_CullFace(GL_NONE);
10545 R_EntityMatrix(&identitymatrix);
10547 // R_Mesh_ResetTextureState();
10549 i = surfacelist[0];
10550 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10551 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10552 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10553 surfacelist[0] < 0 ? 0.5f : 0.125f);
10555 if (VectorCompare(loc->mins, loc->maxs))
10557 VectorSet(size, 2, 2, 2);
10558 VectorMA(loc->mins, -0.5f, size, mins);
10562 VectorCopy(loc->mins, mins);
10563 VectorSubtract(loc->maxs, loc->mins, size);
10566 for (i = 0;i < 6*4*3;)
10567 for (j = 0;j < 3;j++, i++)
10568 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10570 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10571 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10572 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10575 void R_DrawLocs(void)
10578 cl_locnode_t *loc, *nearestloc;
10580 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10581 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10583 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10584 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10588 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10590 if (decalsystem->decals)
10591 Mem_Free(decalsystem->decals);
10592 memset(decalsystem, 0, sizeof(*decalsystem));
10595 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)
10598 tridecal_t *decals;
10601 // expand or initialize the system
10602 if (decalsystem->maxdecals <= decalsystem->numdecals)
10604 decalsystem_t old = *decalsystem;
10605 qboolean useshortelements;
10606 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10607 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10608 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)));
10609 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10610 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10611 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10612 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10613 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10614 if (decalsystem->numdecals)
10615 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10617 Mem_Free(old.decals);
10618 for (i = 0;i < decalsystem->maxdecals*3;i++)
10619 decalsystem->element3i[i] = i;
10620 if (useshortelements)
10621 for (i = 0;i < decalsystem->maxdecals*3;i++)
10622 decalsystem->element3s[i] = i;
10625 // grab a decal and search for another free slot for the next one
10626 decals = decalsystem->decals;
10627 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10628 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10630 decalsystem->freedecal = i;
10631 if (decalsystem->numdecals <= i)
10632 decalsystem->numdecals = i + 1;
10634 // initialize the decal
10636 decal->triangleindex = triangleindex;
10637 decal->surfaceindex = surfaceindex;
10638 decal->decalsequence = decalsequence;
10639 decal->color4f[0][0] = c0[0];
10640 decal->color4f[0][1] = c0[1];
10641 decal->color4f[0][2] = c0[2];
10642 decal->color4f[0][3] = 1;
10643 decal->color4f[1][0] = c1[0];
10644 decal->color4f[1][1] = c1[1];
10645 decal->color4f[1][2] = c1[2];
10646 decal->color4f[1][3] = 1;
10647 decal->color4f[2][0] = c2[0];
10648 decal->color4f[2][1] = c2[1];
10649 decal->color4f[2][2] = c2[2];
10650 decal->color4f[2][3] = 1;
10651 decal->vertex3f[0][0] = v0[0];
10652 decal->vertex3f[0][1] = v0[1];
10653 decal->vertex3f[0][2] = v0[2];
10654 decal->vertex3f[1][0] = v1[0];
10655 decal->vertex3f[1][1] = v1[1];
10656 decal->vertex3f[1][2] = v1[2];
10657 decal->vertex3f[2][0] = v2[0];
10658 decal->vertex3f[2][1] = v2[1];
10659 decal->vertex3f[2][2] = v2[2];
10660 decal->texcoord2f[0][0] = t0[0];
10661 decal->texcoord2f[0][1] = t0[1];
10662 decal->texcoord2f[1][0] = t1[0];
10663 decal->texcoord2f[1][1] = t1[1];
10664 decal->texcoord2f[2][0] = t2[0];
10665 decal->texcoord2f[2][1] = t2[1];
10666 TriangleNormal(v0, v1, v2, decal->plane);
10667 VectorNormalize(decal->plane);
10668 decal->plane[3] = DotProduct(v0, decal->plane);
10671 extern cvar_t cl_decals_bias;
10672 extern cvar_t cl_decals_models;
10673 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10674 // baseparms, parms, temps
10675 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)
10680 const float *vertex3f;
10681 const float *normal3f;
10683 float points[2][9][3];
10690 e = rsurface.modelelement3i + 3*triangleindex;
10692 vertex3f = rsurface.modelvertex3f;
10693 normal3f = rsurface.modelnormal3f;
10697 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10699 index = 3*e[cornerindex];
10700 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10705 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10707 index = 3*e[cornerindex];
10708 VectorCopy(vertex3f + index, v[cornerindex]);
10713 //TriangleNormal(v[0], v[1], v[2], normal);
10714 //if (DotProduct(normal, localnormal) < 0.0f)
10716 // clip by each of the box planes formed from the projection matrix
10717 // if anything survives, we emit the decal
10718 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]);
10721 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]);
10724 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]);
10727 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]);
10730 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]);
10733 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]);
10736 // some part of the triangle survived, so we have to accept it...
10739 // dynamic always uses the original triangle
10741 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10743 index = 3*e[cornerindex];
10744 VectorCopy(vertex3f + index, v[cornerindex]);
10747 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10749 // convert vertex positions to texcoords
10750 Matrix4x4_Transform(projection, v[cornerindex], temp);
10751 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10752 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10753 // calculate distance fade from the projection origin
10754 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10755 f = bound(0.0f, f, 1.0f);
10756 c[cornerindex][0] = r * f;
10757 c[cornerindex][1] = g * f;
10758 c[cornerindex][2] = b * f;
10759 c[cornerindex][3] = 1.0f;
10760 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10763 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);
10765 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10766 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);
10768 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)
10770 matrix4x4_t projection;
10771 decalsystem_t *decalsystem;
10774 const msurface_t *surface;
10775 const msurface_t *surfaces;
10776 const int *surfacelist;
10777 const texture_t *texture;
10779 int numsurfacelist;
10780 int surfacelistindex;
10783 float localorigin[3];
10784 float localnormal[3];
10785 float localmins[3];
10786 float localmaxs[3];
10789 float planes[6][4];
10792 int bih_triangles_count;
10793 int bih_triangles[256];
10794 int bih_surfaces[256];
10796 decalsystem = &ent->decalsystem;
10797 model = ent->model;
10798 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10800 R_DecalSystem_Reset(&ent->decalsystem);
10804 if (!model->brush.data_leafs && !cl_decals_models.integer)
10806 if (decalsystem->model)
10807 R_DecalSystem_Reset(decalsystem);
10811 if (decalsystem->model != model)
10812 R_DecalSystem_Reset(decalsystem);
10813 decalsystem->model = model;
10815 RSurf_ActiveModelEntity(ent, true, false, false);
10817 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10818 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10819 VectorNormalize(localnormal);
10820 localsize = worldsize*rsurface.inversematrixscale;
10821 localmins[0] = localorigin[0] - localsize;
10822 localmins[1] = localorigin[1] - localsize;
10823 localmins[2] = localorigin[2] - localsize;
10824 localmaxs[0] = localorigin[0] + localsize;
10825 localmaxs[1] = localorigin[1] + localsize;
10826 localmaxs[2] = localorigin[2] + localsize;
10828 //VectorCopy(localnormal, planes[4]);
10829 //VectorVectors(planes[4], planes[2], planes[0]);
10830 AnglesFromVectors(angles, localnormal, NULL, false);
10831 AngleVectors(angles, planes[0], planes[2], planes[4]);
10832 VectorNegate(planes[0], planes[1]);
10833 VectorNegate(planes[2], planes[3]);
10834 VectorNegate(planes[4], planes[5]);
10835 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10836 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10837 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10838 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10839 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10840 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10845 matrix4x4_t forwardprojection;
10846 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10847 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10852 float projectionvector[4][3];
10853 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10854 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10855 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10856 projectionvector[0][0] = planes[0][0] * ilocalsize;
10857 projectionvector[0][1] = planes[1][0] * ilocalsize;
10858 projectionvector[0][2] = planes[2][0] * ilocalsize;
10859 projectionvector[1][0] = planes[0][1] * ilocalsize;
10860 projectionvector[1][1] = planes[1][1] * ilocalsize;
10861 projectionvector[1][2] = planes[2][1] * ilocalsize;
10862 projectionvector[2][0] = planes[0][2] * ilocalsize;
10863 projectionvector[2][1] = planes[1][2] * ilocalsize;
10864 projectionvector[2][2] = planes[2][2] * ilocalsize;
10865 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10866 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10867 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10868 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10872 dynamic = model->surfmesh.isanimated;
10873 numsurfacelist = model->nummodelsurfaces;
10874 surfacelist = model->sortedmodelsurfaces;
10875 surfaces = model->data_surfaces;
10878 bih_triangles_count = -1;
10881 if(model->render_bih.numleafs)
10882 bih = &model->render_bih;
10883 else if(model->collision_bih.numleafs)
10884 bih = &model->collision_bih;
10887 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10888 if(bih_triangles_count == 0)
10890 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10892 if(bih_triangles_count > 0)
10894 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10896 surfaceindex = bih_surfaces[triangleindex];
10897 surface = surfaces + surfaceindex;
10898 texture = surface->texture;
10899 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10901 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10903 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10908 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10910 surfaceindex = surfacelist[surfacelistindex];
10911 surface = surfaces + surfaceindex;
10912 // check cull box first because it rejects more than any other check
10913 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10915 // skip transparent surfaces
10916 texture = surface->texture;
10917 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10919 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10921 numtriangles = surface->num_triangles;
10922 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10923 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10928 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10929 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)
10931 int renderentityindex;
10932 float worldmins[3];
10933 float worldmaxs[3];
10934 entity_render_t *ent;
10936 if (!cl_decals_newsystem.integer)
10939 worldmins[0] = worldorigin[0] - worldsize;
10940 worldmins[1] = worldorigin[1] - worldsize;
10941 worldmins[2] = worldorigin[2] - worldsize;
10942 worldmaxs[0] = worldorigin[0] + worldsize;
10943 worldmaxs[1] = worldorigin[1] + worldsize;
10944 worldmaxs[2] = worldorigin[2] + worldsize;
10946 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10948 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10950 ent = r_refdef.scene.entities[renderentityindex];
10951 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10954 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10958 typedef struct r_decalsystem_splatqueue_s
10960 vec3_t worldorigin;
10961 vec3_t worldnormal;
10967 r_decalsystem_splatqueue_t;
10969 int r_decalsystem_numqueued = 0;
10970 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10972 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)
10974 r_decalsystem_splatqueue_t *queue;
10976 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10979 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10980 VectorCopy(worldorigin, queue->worldorigin);
10981 VectorCopy(worldnormal, queue->worldnormal);
10982 Vector4Set(queue->color, r, g, b, a);
10983 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10984 queue->worldsize = worldsize;
10985 queue->decalsequence = cl.decalsequence++;
10988 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10991 r_decalsystem_splatqueue_t *queue;
10993 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10994 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);
10995 r_decalsystem_numqueued = 0;
10998 extern cvar_t cl_decals_max;
10999 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11002 decalsystem_t *decalsystem = &ent->decalsystem;
11009 if (!decalsystem->numdecals)
11012 if (r_showsurfaces.integer)
11015 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11017 R_DecalSystem_Reset(decalsystem);
11021 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11022 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11024 if (decalsystem->lastupdatetime)
11025 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11028 decalsystem->lastupdatetime = r_refdef.scene.time;
11029 decal = decalsystem->decals;
11030 numdecals = decalsystem->numdecals;
11032 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11034 if (decal->color4f[0][3])
11036 decal->lived += frametime;
11037 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11039 memset(decal, 0, sizeof(*decal));
11040 if (decalsystem->freedecal > i)
11041 decalsystem->freedecal = i;
11045 decal = decalsystem->decals;
11046 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11049 // collapse the array by shuffling the tail decals into the gaps
11052 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11053 decalsystem->freedecal++;
11054 if (decalsystem->freedecal == numdecals)
11056 decal[decalsystem->freedecal] = decal[--numdecals];
11059 decalsystem->numdecals = numdecals;
11061 if (numdecals <= 0)
11063 // if there are no decals left, reset decalsystem
11064 R_DecalSystem_Reset(decalsystem);
11068 extern skinframe_t *decalskinframe;
11069 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11072 decalsystem_t *decalsystem = &ent->decalsystem;
11081 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11084 numdecals = decalsystem->numdecals;
11088 if (r_showsurfaces.integer)
11091 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11093 R_DecalSystem_Reset(decalsystem);
11097 // if the model is static it doesn't matter what value we give for
11098 // wantnormals and wanttangents, so this logic uses only rules applicable
11099 // to a model, knowing that they are meaningless otherwise
11100 if (ent == r_refdef.scene.worldentity)
11101 RSurf_ActiveWorldEntity();
11103 RSurf_ActiveModelEntity(ent, false, false, false);
11105 decalsystem->lastupdatetime = r_refdef.scene.time;
11106 decal = decalsystem->decals;
11108 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11110 // update vertex positions for animated models
11111 v3f = decalsystem->vertex3f;
11112 c4f = decalsystem->color4f;
11113 t2f = decalsystem->texcoord2f;
11114 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11116 if (!decal->color4f[0][3])
11119 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11123 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11126 // update color values for fading decals
11127 if (decal->lived >= cl_decals_time.value)
11128 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11132 c4f[ 0] = decal->color4f[0][0] * alpha;
11133 c4f[ 1] = decal->color4f[0][1] * alpha;
11134 c4f[ 2] = decal->color4f[0][2] * alpha;
11136 c4f[ 4] = decal->color4f[1][0] * alpha;
11137 c4f[ 5] = decal->color4f[1][1] * alpha;
11138 c4f[ 6] = decal->color4f[1][2] * alpha;
11140 c4f[ 8] = decal->color4f[2][0] * alpha;
11141 c4f[ 9] = decal->color4f[2][1] * alpha;
11142 c4f[10] = decal->color4f[2][2] * alpha;
11145 t2f[0] = decal->texcoord2f[0][0];
11146 t2f[1] = decal->texcoord2f[0][1];
11147 t2f[2] = decal->texcoord2f[1][0];
11148 t2f[3] = decal->texcoord2f[1][1];
11149 t2f[4] = decal->texcoord2f[2][0];
11150 t2f[5] = decal->texcoord2f[2][1];
11152 // update vertex positions for animated models
11153 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11155 e = rsurface.modelelement3i + 3*decal->triangleindex;
11156 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11157 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11158 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11162 VectorCopy(decal->vertex3f[0], v3f);
11163 VectorCopy(decal->vertex3f[1], v3f + 3);
11164 VectorCopy(decal->vertex3f[2], v3f + 6);
11167 if (r_refdef.fogenabled)
11169 alpha = RSurf_FogVertex(v3f);
11170 VectorScale(c4f, alpha, c4f);
11171 alpha = RSurf_FogVertex(v3f + 3);
11172 VectorScale(c4f + 4, alpha, c4f + 4);
11173 alpha = RSurf_FogVertex(v3f + 6);
11174 VectorScale(c4f + 8, alpha, c4f + 8);
11185 r_refdef.stats.drawndecals += numtris;
11187 // now render the decals all at once
11188 // (this assumes they all use one particle font texture!)
11189 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);
11190 // R_Mesh_ResetTextureState();
11191 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11192 GL_DepthMask(false);
11193 GL_DepthRange(0, 1);
11194 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11195 GL_DepthTest(true);
11196 GL_CullFace(GL_NONE);
11197 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11198 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11199 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11203 static void R_DrawModelDecals(void)
11207 // fade faster when there are too many decals
11208 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11209 for (i = 0;i < r_refdef.scene.numentities;i++)
11210 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11212 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11213 for (i = 0;i < r_refdef.scene.numentities;i++)
11214 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11215 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11217 R_DecalSystem_ApplySplatEntitiesQueue();
11219 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11220 for (i = 0;i < r_refdef.scene.numentities;i++)
11221 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11223 r_refdef.stats.totaldecals += numdecals;
11225 if (r_showsurfaces.integer)
11228 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11230 for (i = 0;i < r_refdef.scene.numentities;i++)
11232 if (!r_refdef.viewcache.entityvisible[i])
11234 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11235 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11239 extern cvar_t mod_collision_bih;
11240 void R_DrawDebugModel(void)
11242 entity_render_t *ent = rsurface.entity;
11243 int i, j, k, l, flagsmask;
11244 const msurface_t *surface;
11245 dp_model_t *model = ent->model;
11248 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11251 if (r_showoverdraw.value > 0)
11253 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11254 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11255 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11256 GL_DepthTest(false);
11257 GL_DepthMask(false);
11258 GL_DepthRange(0, 1);
11259 GL_BlendFunc(GL_ONE, GL_ONE);
11260 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11262 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11264 rsurface.texture = R_GetCurrentTexture(surface->texture);
11265 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11267 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11268 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11269 if (!rsurface.texture->currentlayers->depthmask)
11270 GL_Color(c, 0, 0, 1.0f);
11271 else if (ent == r_refdef.scene.worldentity)
11272 GL_Color(c, c, c, 1.0f);
11274 GL_Color(0, c, 0, 1.0f);
11275 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11279 rsurface.texture = NULL;
11282 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11284 // R_Mesh_ResetTextureState();
11285 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11286 GL_DepthRange(0, 1);
11287 GL_DepthTest(!r_showdisabledepthtest.integer);
11288 GL_DepthMask(false);
11289 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11291 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11295 qboolean cullbox = ent == r_refdef.scene.worldentity;
11296 const q3mbrush_t *brush;
11297 const bih_t *bih = &model->collision_bih;
11298 const bih_leaf_t *bihleaf;
11299 float vertex3f[3][3];
11300 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11302 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11304 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11306 switch (bihleaf->type)
11309 brush = model->brush.data_brushes + bihleaf->itemindex;
11310 if (brush->colbrushf && brush->colbrushf->numtriangles)
11312 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);
11313 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11314 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11317 case BIH_COLLISIONTRIANGLE:
11318 triangleindex = bihleaf->itemindex;
11319 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11320 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11321 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11322 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);
11323 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11324 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11326 case BIH_RENDERTRIANGLE:
11327 triangleindex = bihleaf->itemindex;
11328 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11329 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11330 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11331 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);
11332 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11333 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11339 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11341 if (r_showtris.integer && qglPolygonMode)
11343 if (r_showdisabledepthtest.integer)
11345 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11346 GL_DepthMask(false);
11350 GL_BlendFunc(GL_ONE, GL_ZERO);
11351 GL_DepthMask(true);
11353 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11354 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11356 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11358 rsurface.texture = R_GetCurrentTexture(surface->texture);
11359 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11361 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11362 if (!rsurface.texture->currentlayers->depthmask)
11363 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11364 else if (ent == r_refdef.scene.worldentity)
11365 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11367 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11368 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11372 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11373 rsurface.texture = NULL;
11376 if (r_shownormals.value != 0 && qglBegin)
11378 if (r_showdisabledepthtest.integer)
11380 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11381 GL_DepthMask(false);
11385 GL_BlendFunc(GL_ONE, GL_ZERO);
11386 GL_DepthMask(true);
11388 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11390 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11392 rsurface.texture = R_GetCurrentTexture(surface->texture);
11393 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11395 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11396 qglBegin(GL_LINES);
11397 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11399 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11401 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11402 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11403 qglVertex3f(v[0], v[1], v[2]);
11404 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11405 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11406 qglVertex3f(v[0], v[1], v[2]);
11409 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11411 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11413 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11414 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11415 qglVertex3f(v[0], v[1], v[2]);
11416 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11417 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11418 qglVertex3f(v[0], v[1], v[2]);
11421 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11423 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11425 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11426 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11427 qglVertex3f(v[0], v[1], v[2]);
11428 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11429 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11430 qglVertex3f(v[0], v[1], v[2]);
11433 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11435 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11437 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11438 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11439 qglVertex3f(v[0], v[1], v[2]);
11440 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11441 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11442 qglVertex3f(v[0], v[1], v[2]);
11449 rsurface.texture = NULL;
11453 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11454 int r_maxsurfacelist = 0;
11455 const msurface_t **r_surfacelist = NULL;
11456 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11458 int i, j, endj, flagsmask;
11459 dp_model_t *model = r_refdef.scene.worldmodel;
11460 msurface_t *surfaces;
11461 unsigned char *update;
11462 int numsurfacelist = 0;
11466 if (r_maxsurfacelist < model->num_surfaces)
11468 r_maxsurfacelist = model->num_surfaces;
11470 Mem_Free((msurface_t**)r_surfacelist);
11471 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11474 RSurf_ActiveWorldEntity();
11476 surfaces = model->data_surfaces;
11477 update = model->brushq1.lightmapupdateflags;
11479 // update light styles on this submodel
11480 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11482 model_brush_lightstyleinfo_t *style;
11483 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11485 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11487 int *list = style->surfacelist;
11488 style->value = r_refdef.scene.lightstylevalue[style->style];
11489 for (j = 0;j < style->numsurfaces;j++)
11490 update[list[j]] = true;
11495 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11499 R_DrawDebugModel();
11500 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11504 rsurface.lightmaptexture = NULL;
11505 rsurface.deluxemaptexture = NULL;
11506 rsurface.uselightmaptexture = false;
11507 rsurface.texture = NULL;
11508 rsurface.rtlight = NULL;
11509 numsurfacelist = 0;
11510 // add visible surfaces to draw list
11511 for (i = 0;i < model->nummodelsurfaces;i++)
11513 j = model->sortedmodelsurfaces[i];
11514 if (r_refdef.viewcache.world_surfacevisible[j])
11515 r_surfacelist[numsurfacelist++] = surfaces + j;
11517 // update lightmaps if needed
11518 if (model->brushq1.firstrender)
11520 model->brushq1.firstrender = false;
11521 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11523 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11527 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11528 if (r_refdef.viewcache.world_surfacevisible[j])
11530 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11532 // don't do anything if there were no surfaces
11533 if (!numsurfacelist)
11535 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11538 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11540 // add to stats if desired
11541 if (r_speeds.integer && !skysurfaces && !depthonly)
11543 r_refdef.stats.world_surfaces += numsurfacelist;
11544 for (j = 0;j < numsurfacelist;j++)
11545 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11548 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11551 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11553 int i, j, endj, flagsmask;
11554 dp_model_t *model = ent->model;
11555 msurface_t *surfaces;
11556 unsigned char *update;
11557 int numsurfacelist = 0;
11561 if (r_maxsurfacelist < model->num_surfaces)
11563 r_maxsurfacelist = model->num_surfaces;
11565 Mem_Free((msurface_t **)r_surfacelist);
11566 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11569 // if the model is static it doesn't matter what value we give for
11570 // wantnormals and wanttangents, so this logic uses only rules applicable
11571 // to a model, knowing that they are meaningless otherwise
11572 if (ent == r_refdef.scene.worldentity)
11573 RSurf_ActiveWorldEntity();
11574 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11575 RSurf_ActiveModelEntity(ent, false, false, false);
11577 RSurf_ActiveModelEntity(ent, true, true, true);
11578 else if (depthonly)
11580 switch (vid.renderpath)
11582 case RENDERPATH_GL20:
11583 case RENDERPATH_D3D9:
11584 case RENDERPATH_D3D10:
11585 case RENDERPATH_D3D11:
11586 case RENDERPATH_SOFT:
11587 case RENDERPATH_GLES2:
11588 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11590 case RENDERPATH_GL11:
11591 case RENDERPATH_GL13:
11592 case RENDERPATH_GLES1:
11593 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11599 switch (vid.renderpath)
11601 case RENDERPATH_GL20:
11602 case RENDERPATH_D3D9:
11603 case RENDERPATH_D3D10:
11604 case RENDERPATH_D3D11:
11605 case RENDERPATH_SOFT:
11606 case RENDERPATH_GLES2:
11607 RSurf_ActiveModelEntity(ent, true, true, false);
11609 case RENDERPATH_GL11:
11610 case RENDERPATH_GL13:
11611 case RENDERPATH_GLES1:
11612 RSurf_ActiveModelEntity(ent, true, false, false);
11617 surfaces = model->data_surfaces;
11618 update = model->brushq1.lightmapupdateflags;
11620 // update light styles
11621 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11623 model_brush_lightstyleinfo_t *style;
11624 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11626 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11628 int *list = style->surfacelist;
11629 style->value = r_refdef.scene.lightstylevalue[style->style];
11630 for (j = 0;j < style->numsurfaces;j++)
11631 update[list[j]] = true;
11636 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11640 R_DrawDebugModel();
11641 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11645 rsurface.lightmaptexture = NULL;
11646 rsurface.deluxemaptexture = NULL;
11647 rsurface.uselightmaptexture = false;
11648 rsurface.texture = NULL;
11649 rsurface.rtlight = NULL;
11650 numsurfacelist = 0;
11651 // add visible surfaces to draw list
11652 for (i = 0;i < model->nummodelsurfaces;i++)
11653 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11654 // don't do anything if there were no surfaces
11655 if (!numsurfacelist)
11657 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11660 // update lightmaps if needed
11664 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11669 R_BuildLightMap(ent, surfaces + j);
11674 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11676 R_BuildLightMap(ent, surfaces + j);
11677 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11679 // add to stats if desired
11680 if (r_speeds.integer && !skysurfaces && !depthonly)
11682 r_refdef.stats.entities_surfaces += numsurfacelist;
11683 for (j = 0;j < numsurfacelist;j++)
11684 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11687 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11690 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11692 static texture_t texture;
11693 static msurface_t surface;
11694 const msurface_t *surfacelist = &surface;
11696 // fake enough texture and surface state to render this geometry
11698 texture.update_lastrenderframe = -1; // regenerate this texture
11699 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11700 texture.currentskinframe = skinframe;
11701 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11702 texture.offsetmapping = OFFSETMAPPING_OFF;
11703 texture.offsetscale = 1;
11704 texture.specularscalemod = 1;
11705 texture.specularpowermod = 1;
11707 surface.texture = &texture;
11708 surface.num_triangles = numtriangles;
11709 surface.num_firsttriangle = firsttriangle;
11710 surface.num_vertices = numvertices;
11711 surface.num_firstvertex = firstvertex;
11714 rsurface.texture = R_GetCurrentTexture(surface.texture);
11715 rsurface.lightmaptexture = NULL;
11716 rsurface.deluxemaptexture = NULL;
11717 rsurface.uselightmaptexture = false;
11718 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11721 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)
11723 static msurface_t surface;
11724 const msurface_t *surfacelist = &surface;
11726 // fake enough texture and surface state to render this geometry
11727 surface.texture = texture;
11728 surface.num_triangles = numtriangles;
11729 surface.num_firsttriangle = firsttriangle;
11730 surface.num_vertices = numvertices;
11731 surface.num_firstvertex = firstvertex;
11734 rsurface.texture = R_GetCurrentTexture(surface.texture);
11735 rsurface.lightmaptexture = NULL;
11736 rsurface.deluxemaptexture = NULL;
11737 rsurface.uselightmaptexture = false;
11738 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);