2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_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 usegamma, 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 // LordHavoc: VorteX broke the game by doing this, and did not cvar it properly, and did not add the proper checks (r_texture_sRGB_2d.integer would need to be checked), and it breaks with vid_sRGB where the gamma ramps are altered...
1914 // if (usegamma && r_texture_gammaramps && v_glslgamma.integer && !vid_gammatables_trivial)
1915 // permutation |= SHADERPERMUTATION_GAMMARAMPS;
1916 else if (texturemode == GL_ADD)
1917 permutation |= SHADERPERMUTATION_GLOW;
1918 else if (texturemode == GL_DECAL)
1919 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1921 texturemode = GL_MODULATE;
1922 if (vid.allowalphatocoverage)
1923 GL_AlphaToCoverage(false);
1924 switch (vid.renderpath)
1926 case RENDERPATH_D3D9:
1928 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1929 R_Mesh_TexBind(GL20TU_FIRST , first );
1930 R_Mesh_TexBind(GL20TU_SECOND, second);
1931 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1932 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1935 case RENDERPATH_D3D10:
1936 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1938 case RENDERPATH_D3D11:
1939 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1941 case RENDERPATH_GL20:
1942 case RENDERPATH_GLES2:
1943 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1944 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1945 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1946 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1947 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1949 case RENDERPATH_GL13:
1950 case RENDERPATH_GLES1:
1951 R_Mesh_TexBind(0, first );
1952 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1953 R_Mesh_TexBind(1, second);
1955 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1957 case RENDERPATH_GL11:
1958 R_Mesh_TexBind(0, first );
1960 case RENDERPATH_SOFT:
1961 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1962 R_Mesh_TexBind(GL20TU_FIRST , first );
1963 R_Mesh_TexBind(GL20TU_SECOND, second);
1968 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1970 unsigned int permutation = 0;
1971 if (r_trippy.integer && !notrippy)
1972 permutation |= SHADERPERMUTATION_TRIPPY;
1973 if (vid.allowalphatocoverage)
1974 GL_AlphaToCoverage(false);
1975 switch (vid.renderpath)
1977 case RENDERPATH_D3D9:
1979 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1982 case RENDERPATH_D3D10:
1983 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1985 case RENDERPATH_D3D11:
1986 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1988 case RENDERPATH_GL20:
1989 case RENDERPATH_GLES2:
1990 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1992 case RENDERPATH_GL13:
1993 case RENDERPATH_GLES1:
1994 R_Mesh_TexBind(0, 0);
1995 R_Mesh_TexBind(1, 0);
1997 case RENDERPATH_GL11:
1998 R_Mesh_TexBind(0, 0);
2000 case RENDERPATH_SOFT:
2001 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006 void R_SetupShader_ShowDepth(qboolean notrippy)
2008 int permutation = 0;
2009 if (r_trippy.integer && !notrippy)
2010 permutation |= SHADERPERMUTATION_TRIPPY;
2011 if (vid.allowalphatocoverage)
2012 GL_AlphaToCoverage(false);
2013 switch (vid.renderpath)
2015 case RENDERPATH_D3D9:
2017 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2020 case RENDERPATH_D3D10:
2021 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2023 case RENDERPATH_D3D11:
2024 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2026 case RENDERPATH_GL20:
2027 case RENDERPATH_GLES2:
2028 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2030 case RENDERPATH_GL13:
2031 case RENDERPATH_GLES1:
2033 case RENDERPATH_GL11:
2035 case RENDERPATH_SOFT:
2036 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2041 extern qboolean r_shadow_usingdeferredprepass;
2042 extern cvar_t r_shadow_deferred_8bitrange;
2043 extern rtexture_t *r_shadow_attenuationgradienttexture;
2044 extern rtexture_t *r_shadow_attenuation2dtexture;
2045 extern rtexture_t *r_shadow_attenuation3dtexture;
2046 extern qboolean r_shadow_usingshadowmap2d;
2047 extern qboolean r_shadow_usingshadowmaportho;
2048 extern float r_shadow_shadowmap_texturescale[2];
2049 extern float r_shadow_shadowmap_parameters[4];
2050 extern qboolean r_shadow_shadowmapvsdct;
2051 extern qboolean r_shadow_shadowmapsampler;
2052 extern int r_shadow_shadowmappcf;
2053 extern rtexture_t *r_shadow_shadowmap2dtexture;
2054 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2055 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2056 extern matrix4x4_t r_shadow_shadowmapmatrix;
2057 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2058 extern int r_shadow_prepass_width;
2059 extern int r_shadow_prepass_height;
2060 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2061 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2062 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2063 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2064 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2066 #define BLENDFUNC_ALLOWS_COLORMOD 1
2067 #define BLENDFUNC_ALLOWS_FOG 2
2068 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2069 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2070 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2071 static int R_BlendFuncFlags(int src, int dst)
2075 // a blendfunc allows colormod if:
2076 // a) it can never keep the destination pixel invariant, or
2077 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2078 // this is to prevent unintended side effects from colormod
2080 // a blendfunc allows fog if:
2081 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2082 // this is to prevent unintended side effects from fog
2084 // these checks are the output of fogeval.pl
2086 r |= BLENDFUNC_ALLOWS_COLORMOD;
2087 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2088 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2089 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2091 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2092 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2093 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2095 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2096 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2097 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2098 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2100 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2101 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2102 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2106 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2107 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112 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)
2114 // select a permutation of the lighting shader appropriate to this
2115 // combination of texture, entity, light source, and fogging, only use the
2116 // minimum features necessary to avoid wasting rendering time in the
2117 // fragment shader on features that are not being used
2118 unsigned int permutation = 0;
2119 unsigned int mode = 0;
2121 static float dummy_colormod[3] = {1, 1, 1};
2122 float *colormod = rsurface.colormod;
2124 matrix4x4_t tempmatrix;
2125 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2126 if (r_trippy.integer && !notrippy)
2127 permutation |= SHADERPERMUTATION_TRIPPY;
2128 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2129 permutation |= SHADERPERMUTATION_ALPHAKILL;
2130 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2131 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2132 if (rsurfacepass == RSURFPASS_BACKGROUND)
2134 // distorted background
2135 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2137 mode = SHADERMODE_WATER;
2138 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2140 // this is the right thing to do for wateralpha
2141 GL_BlendFunc(GL_ONE, GL_ZERO);
2142 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2146 // this is the right thing to do for entity alpha
2147 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2148 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2151 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2153 mode = SHADERMODE_REFRACTION;
2154 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2155 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2159 mode = SHADERMODE_GENERIC;
2160 permutation |= SHADERPERMUTATION_DIFFUSE;
2161 GL_BlendFunc(GL_ONE, GL_ZERO);
2162 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2164 if (vid.allowalphatocoverage)
2165 GL_AlphaToCoverage(false);
2167 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2169 if (r_glsl_offsetmapping.integer)
2171 switch(rsurface.texture->offsetmapping)
2173 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2174 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2175 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2176 case OFFSETMAPPING_OFF: break;
2179 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2180 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2181 // normalmap (deferred prepass), may use alpha test on diffuse
2182 mode = SHADERMODE_DEFERREDGEOMETRY;
2183 GL_BlendFunc(GL_ONE, GL_ZERO);
2184 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2185 if (vid.allowalphatocoverage)
2186 GL_AlphaToCoverage(false);
2188 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2190 if (r_glsl_offsetmapping.integer)
2192 switch(rsurface.texture->offsetmapping)
2194 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2195 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2197 case OFFSETMAPPING_OFF: break;
2200 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2201 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2203 mode = SHADERMODE_LIGHTSOURCE;
2204 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2205 permutation |= SHADERPERMUTATION_CUBEFILTER;
2206 if (diffusescale > 0)
2207 permutation |= SHADERPERMUTATION_DIFFUSE;
2208 if (specularscale > 0)
2209 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2210 if (r_refdef.fogenabled)
2211 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2212 if (rsurface.texture->colormapping)
2213 permutation |= SHADERPERMUTATION_COLORMAPPING;
2214 if (r_shadow_usingshadowmap2d)
2216 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2217 if(r_shadow_shadowmapvsdct)
2218 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2220 if (r_shadow_shadowmapsampler)
2221 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2222 if (r_shadow_shadowmappcf > 1)
2223 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2224 else if (r_shadow_shadowmappcf)
2225 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2227 if (rsurface.texture->reflectmasktexture)
2228 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2229 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2230 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2231 if (vid.allowalphatocoverage)
2232 GL_AlphaToCoverage(false);
2234 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2236 if (r_glsl_offsetmapping.integer)
2238 switch(rsurface.texture->offsetmapping)
2240 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2241 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243 case OFFSETMAPPING_OFF: break;
2246 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2247 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2248 // unshaded geometry (fullbright or ambient model lighting)
2249 mode = SHADERMODE_FLATCOLOR;
2250 ambientscale = diffusescale = specularscale = 0;
2251 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2252 permutation |= SHADERPERMUTATION_GLOW;
2253 if (r_refdef.fogenabled)
2254 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2255 if (rsurface.texture->colormapping)
2256 permutation |= SHADERPERMUTATION_COLORMAPPING;
2257 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2259 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2260 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2262 if (r_shadow_shadowmapsampler)
2263 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2264 if (r_shadow_shadowmappcf > 1)
2265 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2266 else if (r_shadow_shadowmappcf)
2267 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2269 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2270 permutation |= SHADERPERMUTATION_REFLECTION;
2271 if (rsurface.texture->reflectmasktexture)
2272 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2273 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2274 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2275 // when using alphatocoverage, we don't need alphakill
2276 if (vid.allowalphatocoverage)
2278 if (r_transparent_alphatocoverage.integer)
2280 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2281 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2284 GL_AlphaToCoverage(false);
2287 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2289 if (r_glsl_offsetmapping.integer)
2291 switch(rsurface.texture->offsetmapping)
2293 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2294 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296 case OFFSETMAPPING_OFF: break;
2299 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2300 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2301 // directional model lighting
2302 mode = SHADERMODE_LIGHTDIRECTION;
2303 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2304 permutation |= SHADERPERMUTATION_GLOW;
2305 permutation |= SHADERPERMUTATION_DIFFUSE;
2306 if (specularscale > 0)
2307 permutation |= SHADERPERMUTATION_SPECULAR;
2308 if (r_refdef.fogenabled)
2309 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2310 if (rsurface.texture->colormapping)
2311 permutation |= SHADERPERMUTATION_COLORMAPPING;
2312 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2314 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2315 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2317 if (r_shadow_shadowmapsampler)
2318 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2319 if (r_shadow_shadowmappcf > 1)
2320 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2321 else if (r_shadow_shadowmappcf)
2322 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2324 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2325 permutation |= SHADERPERMUTATION_REFLECTION;
2326 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2327 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2328 if (rsurface.texture->reflectmasktexture)
2329 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2330 if (r_shadow_bouncegridtexture)
2332 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2333 if (r_shadow_bouncegriddirectional)
2334 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2336 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2337 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2338 // when using alphatocoverage, we don't need alphakill
2339 if (vid.allowalphatocoverage)
2341 if (r_transparent_alphatocoverage.integer)
2343 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2344 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2347 GL_AlphaToCoverage(false);
2350 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2352 if (r_glsl_offsetmapping.integer)
2354 switch(rsurface.texture->offsetmapping)
2356 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2357 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2358 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2359 case OFFSETMAPPING_OFF: break;
2362 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2363 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2364 // ambient model lighting
2365 mode = SHADERMODE_LIGHTDIRECTION;
2366 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2367 permutation |= SHADERPERMUTATION_GLOW;
2368 if (r_refdef.fogenabled)
2369 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2370 if (rsurface.texture->colormapping)
2371 permutation |= SHADERPERMUTATION_COLORMAPPING;
2372 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2374 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2375 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2377 if (r_shadow_shadowmapsampler)
2378 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2379 if (r_shadow_shadowmappcf > 1)
2380 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2381 else if (r_shadow_shadowmappcf)
2382 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2384 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2385 permutation |= SHADERPERMUTATION_REFLECTION;
2386 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2387 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2388 if (rsurface.texture->reflectmasktexture)
2389 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2390 if (r_shadow_bouncegridtexture)
2392 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2393 if (r_shadow_bouncegriddirectional)
2394 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2396 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2397 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2398 // when using alphatocoverage, we don't need alphakill
2399 if (vid.allowalphatocoverage)
2401 if (r_transparent_alphatocoverage.integer)
2403 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2404 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2407 GL_AlphaToCoverage(false);
2412 if (r_glsl_offsetmapping.integer)
2414 switch(rsurface.texture->offsetmapping)
2416 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2417 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2418 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2419 case OFFSETMAPPING_OFF: break;
2422 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2423 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2425 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2426 permutation |= SHADERPERMUTATION_GLOW;
2427 if (r_refdef.fogenabled)
2428 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2429 if (rsurface.texture->colormapping)
2430 permutation |= SHADERPERMUTATION_COLORMAPPING;
2431 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2433 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2434 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2436 if (r_shadow_shadowmapsampler)
2437 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2438 if (r_shadow_shadowmappcf > 1)
2439 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2440 else if (r_shadow_shadowmappcf)
2441 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2443 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2444 permutation |= SHADERPERMUTATION_REFLECTION;
2445 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2446 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2447 if (rsurface.texture->reflectmasktexture)
2448 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2449 if (FAKELIGHT_ENABLED)
2451 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2452 mode = SHADERMODE_FAKELIGHT;
2453 permutation |= SHADERPERMUTATION_DIFFUSE;
2454 if (specularscale > 0)
2455 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2457 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2459 // deluxemapping (light direction texture)
2460 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2461 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2463 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2464 permutation |= SHADERPERMUTATION_DIFFUSE;
2465 if (specularscale > 0)
2466 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2468 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2470 // fake deluxemapping (uniform light direction in tangentspace)
2471 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2472 permutation |= SHADERPERMUTATION_DIFFUSE;
2473 if (specularscale > 0)
2474 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2476 else if (rsurface.uselightmaptexture)
2478 // ordinary lightmapping (q1bsp, q3bsp)
2479 mode = SHADERMODE_LIGHTMAP;
2483 // ordinary vertex coloring (q3bsp)
2484 mode = SHADERMODE_VERTEXCOLOR;
2486 if (r_shadow_bouncegridtexture)
2488 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2489 if (r_shadow_bouncegriddirectional)
2490 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2492 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2493 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494 // when using alphatocoverage, we don't need alphakill
2495 if (vid.allowalphatocoverage)
2497 if (r_transparent_alphatocoverage.integer)
2499 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2500 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2503 GL_AlphaToCoverage(false);
2506 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2507 colormod = dummy_colormod;
2508 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2509 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2510 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2511 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2512 switch(vid.renderpath)
2514 case RENDERPATH_D3D9:
2516 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);
2517 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2518 R_SetupShader_SetPermutationHLSL(mode, permutation);
2519 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2520 if (mode == SHADERMODE_LIGHTSOURCE)
2522 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2523 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2527 if (mode == SHADERMODE_LIGHTDIRECTION)
2529 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2532 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2533 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2534 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2535 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2536 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2538 if (mode == SHADERMODE_LIGHTSOURCE)
2540 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2541 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2542 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2543 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2544 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2546 // additive passes are only darkened by fog, not tinted
2547 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2548 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2552 if (mode == SHADERMODE_FLATCOLOR)
2554 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2556 else if (mode == SHADERMODE_LIGHTDIRECTION)
2558 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]);
2559 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2560 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);
2561 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);
2562 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2563 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2564 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2568 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2569 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2570 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);
2571 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);
2572 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2574 // additive passes are only darkened by fog, not tinted
2575 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2576 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2578 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2579 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);
2580 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2581 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2582 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2583 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2584 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2585 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2586 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2587 if (mode == SHADERMODE_WATER)
2588 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2590 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2591 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2592 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2593 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));
2594 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2595 if (rsurface.texture->pantstexture)
2596 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2598 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2599 if (rsurface.texture->shirttexture)
2600 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2602 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2603 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2604 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2605 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2606 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2607 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2608 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2609 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2610 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2611 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2613 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2614 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2616 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2617 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2618 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2619 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2620 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2621 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2622 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2623 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2624 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2625 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2626 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2627 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2628 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2629 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2630 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2631 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2632 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2633 if (rsurfacepass == RSURFPASS_BACKGROUND)
2635 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2636 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2637 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2641 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2643 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2644 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2645 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2646 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2647 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2649 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2650 if (rsurface.rtlight)
2652 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2653 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2658 case RENDERPATH_D3D10:
2659 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2661 case RENDERPATH_D3D11:
2662 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2664 case RENDERPATH_GL20:
2665 case RENDERPATH_GLES2:
2666 if (!vid.useinterleavedarrays)
2668 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);
2669 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2670 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2671 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2672 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2673 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2674 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2675 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2679 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);
2680 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2682 R_SetupShader_SetPermutationGLSL(mode, permutation);
2683 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2684 if (mode == SHADERMODE_LIGHTSOURCE)
2686 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2687 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2688 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2689 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2690 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2691 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);
2693 // additive passes are only darkened by fog, not tinted
2694 if (r_glsl_permutation->loc_FogColor >= 0)
2695 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2696 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2700 if (mode == SHADERMODE_FLATCOLOR)
2702 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2704 else if (mode == SHADERMODE_LIGHTDIRECTION)
2706 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]);
2707 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]);
2708 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);
2709 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);
2710 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);
2711 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]);
2712 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]);
2716 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]);
2717 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]);
2718 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);
2719 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);
2720 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);
2722 // additive passes are only darkened by fog, not tinted
2723 if (r_glsl_permutation->loc_FogColor >= 0)
2725 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2726 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2728 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2730 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);
2731 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]);
2732 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]);
2733 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]);
2734 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]);
2735 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2736 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2737 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2738 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]);
2740 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2741 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2742 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2743 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]);
2744 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]);
2746 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2747 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));
2748 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2749 if (r_glsl_permutation->loc_Color_Pants >= 0)
2751 if (rsurface.texture->pantstexture)
2752 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2754 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2756 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2758 if (rsurface.texture->shirttexture)
2759 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2761 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2763 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]);
2764 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2765 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2766 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2767 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2768 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2769 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2770 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2771 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2773 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]);
2774 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2775 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);}
2776 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2778 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2779 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2780 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2781 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2782 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2783 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2784 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2785 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2786 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2787 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2788 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2789 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2790 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2791 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2792 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);
2793 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2794 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2795 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2796 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2797 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2798 if (rsurfacepass == RSURFPASS_BACKGROUND)
2800 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);
2801 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);
2802 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);
2806 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);
2808 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2809 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2810 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2811 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2812 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2814 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2815 if (rsurface.rtlight)
2817 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2818 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2821 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2824 case RENDERPATH_GL11:
2825 case RENDERPATH_GL13:
2826 case RENDERPATH_GLES1:
2828 case RENDERPATH_SOFT:
2829 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);
2830 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2831 R_SetupShader_SetPermutationSoft(mode, permutation);
2832 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2833 if (mode == SHADERMODE_LIGHTSOURCE)
2835 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2836 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2837 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2838 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2839 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2840 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2842 // additive passes are only darkened by fog, not tinted
2843 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2844 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2848 if (mode == SHADERMODE_FLATCOLOR)
2850 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2852 else if (mode == SHADERMODE_LIGHTDIRECTION)
2854 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]);
2855 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2856 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);
2857 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);
2858 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2859 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]);
2860 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2864 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2865 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2866 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);
2867 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);
2868 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2870 // additive passes are only darkened by fog, not tinted
2871 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2872 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2874 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2875 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);
2876 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2877 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2878 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]);
2879 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]);
2880 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2881 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2882 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2883 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2885 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2886 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2887 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2888 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2889 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]);
2891 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2892 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));
2893 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2894 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2896 if (rsurface.texture->pantstexture)
2897 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2901 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2903 if (rsurface.texture->shirttexture)
2904 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2906 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2908 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2909 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2910 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2911 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2912 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2913 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2914 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2915 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2916 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2918 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2919 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2921 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2922 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2923 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2924 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2925 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2926 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2927 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2928 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2929 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2930 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2931 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2932 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2933 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2934 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2935 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2936 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2937 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2938 if (rsurfacepass == RSURFPASS_BACKGROUND)
2940 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2941 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2942 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2946 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2948 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2949 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2950 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2951 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2952 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2954 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2955 if (rsurface.rtlight)
2957 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2958 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2965 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2967 // select a permutation of the lighting shader appropriate to this
2968 // combination of texture, entity, light source, and fogging, only use the
2969 // minimum features necessary to avoid wasting rendering time in the
2970 // fragment shader on features that are not being used
2971 unsigned int permutation = 0;
2972 unsigned int mode = 0;
2973 const float *lightcolorbase = rtlight->currentcolor;
2974 float ambientscale = rtlight->ambientscale;
2975 float diffusescale = rtlight->diffusescale;
2976 float specularscale = rtlight->specularscale;
2977 // this is the location of the light in view space
2978 vec3_t viewlightorigin;
2979 // this transforms from view space (camera) to light space (cubemap)
2980 matrix4x4_t viewtolight;
2981 matrix4x4_t lighttoview;
2982 float viewtolight16f[16];
2983 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2985 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2986 if (rtlight->currentcubemap != r_texture_whitecube)
2987 permutation |= SHADERPERMUTATION_CUBEFILTER;
2988 if (diffusescale > 0)
2989 permutation |= SHADERPERMUTATION_DIFFUSE;
2990 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2991 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2992 if (r_shadow_usingshadowmap2d)
2994 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2995 if (r_shadow_shadowmapvsdct)
2996 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2998 if (r_shadow_shadowmapsampler)
2999 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3000 if (r_shadow_shadowmappcf > 1)
3001 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3002 else if (r_shadow_shadowmappcf)
3003 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3005 if (vid.allowalphatocoverage)
3006 GL_AlphaToCoverage(false);
3007 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3008 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3009 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3010 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3011 switch(vid.renderpath)
3013 case RENDERPATH_D3D9:
3015 R_SetupShader_SetPermutationHLSL(mode, permutation);
3016 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3017 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3018 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3019 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3020 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3021 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3022 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3023 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3024 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3025 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3027 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3028 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3029 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3030 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3031 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3032 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3035 case RENDERPATH_D3D10:
3036 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3038 case RENDERPATH_D3D11:
3039 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3041 case RENDERPATH_GL20:
3042 case RENDERPATH_GLES2:
3043 R_SetupShader_SetPermutationGLSL(mode, permutation);
3044 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3045 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3046 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);
3047 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);
3048 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);
3049 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]);
3050 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]);
3051 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));
3052 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]);
3053 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3055 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3056 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3057 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3058 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3059 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3060 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3062 case RENDERPATH_GL11:
3063 case RENDERPATH_GL13:
3064 case RENDERPATH_GLES1:
3066 case RENDERPATH_SOFT:
3067 R_SetupShader_SetPermutationGLSL(mode, permutation);
3068 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3069 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3070 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3071 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3072 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3073 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3074 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]);
3075 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));
3076 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3077 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3079 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3080 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3081 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3082 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3083 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3084 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3089 #define SKINFRAME_HASH 1024
3093 int loadsequence; // incremented each level change
3094 memexpandablearray_t array;
3095 skinframe_t *hash[SKINFRAME_HASH];
3098 r_skinframe_t r_skinframe;
3100 void R_SkinFrame_PrepareForPurge(void)
3102 r_skinframe.loadsequence++;
3103 // wrap it without hitting zero
3104 if (r_skinframe.loadsequence >= 200)
3105 r_skinframe.loadsequence = 1;
3108 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3112 // mark the skinframe as used for the purging code
3113 skinframe->loadsequence = r_skinframe.loadsequence;
3116 void R_SkinFrame_Purge(void)
3120 for (i = 0;i < SKINFRAME_HASH;i++)
3122 for (s = r_skinframe.hash[i];s;s = s->next)
3124 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3126 if (s->merged == s->base)
3128 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3129 R_PurgeTexture(s->stain );s->stain = NULL;
3130 R_PurgeTexture(s->merged);s->merged = NULL;
3131 R_PurgeTexture(s->base );s->base = NULL;
3132 R_PurgeTexture(s->pants );s->pants = NULL;
3133 R_PurgeTexture(s->shirt );s->shirt = NULL;
3134 R_PurgeTexture(s->nmap );s->nmap = NULL;
3135 R_PurgeTexture(s->gloss );s->gloss = NULL;
3136 R_PurgeTexture(s->glow );s->glow = NULL;
3137 R_PurgeTexture(s->fog );s->fog = NULL;
3138 R_PurgeTexture(s->reflect);s->reflect = NULL;
3139 s->loadsequence = 0;
3145 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3147 char basename[MAX_QPATH];
3149 Image_StripImageExtension(name, basename, sizeof(basename));
3151 if( last == NULL ) {
3153 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3154 item = r_skinframe.hash[hashindex];
3159 // linearly search through the hash bucket
3160 for( ; item ; item = item->next ) {
3161 if( !strcmp( item->basename, basename ) ) {
3168 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3172 char basename[MAX_QPATH];
3174 Image_StripImageExtension(name, basename, sizeof(basename));
3176 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3177 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3178 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3182 rtexture_t *dyntexture;
3183 // check whether its a dynamic texture
3184 dyntexture = CL_GetDynTexture( basename );
3185 if (!add && !dyntexture)
3187 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3188 memset(item, 0, sizeof(*item));
3189 strlcpy(item->basename, basename, sizeof(item->basename));
3190 item->base = dyntexture; // either NULL or dyntexture handle
3191 item->textureflags = textureflags;
3192 item->comparewidth = comparewidth;
3193 item->compareheight = compareheight;
3194 item->comparecrc = comparecrc;
3195 item->next = r_skinframe.hash[hashindex];
3196 r_skinframe.hash[hashindex] = item;
3198 else if( item->base == NULL )
3200 rtexture_t *dyntexture;
3201 // check whether its a dynamic texture
3202 // 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]
3203 dyntexture = CL_GetDynTexture( basename );
3204 item->base = dyntexture; // either NULL or dyntexture handle
3207 R_SkinFrame_MarkUsed(item);
3211 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3213 unsigned long long avgcolor[5], wsum; \
3221 for(pix = 0; pix < cnt; ++pix) \
3224 for(comp = 0; comp < 3; ++comp) \
3226 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3229 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3231 for(comp = 0; comp < 3; ++comp) \
3232 avgcolor[comp] += getpixel * w; \
3235 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3236 avgcolor[4] += getpixel; \
3238 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3240 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3241 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3242 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3243 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3246 extern cvar_t gl_picmip;
3247 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3250 unsigned char *pixels;
3251 unsigned char *bumppixels;
3252 unsigned char *basepixels = NULL;
3253 int basepixels_width = 0;
3254 int basepixels_height = 0;
3255 skinframe_t *skinframe;
3256 rtexture_t *ddsbase = NULL;
3257 qboolean ddshasalpha = false;
3258 float ddsavgcolor[4];
3259 char basename[MAX_QPATH];
3260 int miplevel = R_PicmipForFlags(textureflags);
3261 int savemiplevel = miplevel;
3264 if (cls.state == ca_dedicated)
3267 // return an existing skinframe if already loaded
3268 // if loading of the first image fails, don't make a new skinframe as it
3269 // would cause all future lookups of this to be missing
3270 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3271 if (skinframe && skinframe->base)
3274 Image_StripImageExtension(name, basename, sizeof(basename));
3276 // check for DDS texture file first
3277 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3279 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3280 if (basepixels == NULL)
3284 // FIXME handle miplevel
3286 if (developer_loading.integer)
3287 Con_Printf("loading skin \"%s\"\n", name);
3289 // we've got some pixels to store, so really allocate this new texture now
3291 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3292 skinframe->stain = NULL;
3293 skinframe->merged = NULL;
3294 skinframe->base = NULL;
3295 skinframe->pants = NULL;
3296 skinframe->shirt = NULL;
3297 skinframe->nmap = NULL;
3298 skinframe->gloss = NULL;
3299 skinframe->glow = NULL;
3300 skinframe->fog = NULL;
3301 skinframe->reflect = NULL;
3302 skinframe->hasalpha = false;
3306 skinframe->base = ddsbase;
3307 skinframe->hasalpha = ddshasalpha;
3308 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3309 if (r_loadfog && skinframe->hasalpha)
3310 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3311 //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]);
3315 basepixels_width = image_width;
3316 basepixels_height = image_height;
3317 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);
3318 if (textureflags & TEXF_ALPHA)
3320 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3322 if (basepixels[j] < 255)
3324 skinframe->hasalpha = true;
3328 if (r_loadfog && skinframe->hasalpha)
3330 // has transparent pixels
3331 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3332 for (j = 0;j < image_width * image_height * 4;j += 4)
3337 pixels[j+3] = basepixels[j+3];
3339 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);
3343 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3344 //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]);
3345 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3346 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3347 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3348 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3353 mymiplevel = savemiplevel;
3354 if (r_loadnormalmap)
3355 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);
3356 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3358 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3359 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3360 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3361 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3364 // _norm is the name used by tenebrae and has been adopted as standard
3365 if (r_loadnormalmap && skinframe->nmap == NULL)
3367 mymiplevel = savemiplevel;
3368 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3370 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);
3374 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3376 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3377 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3378 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);
3380 Mem_Free(bumppixels);
3382 else if (r_shadow_bumpscale_basetexture.value > 0)
3384 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3385 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3386 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);
3389 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3390 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3393 // _luma is supported only for tenebrae compatibility
3394 // _glow is the preferred name
3395 mymiplevel = savemiplevel;
3396 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))))
3398 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);
3399 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3400 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3401 Mem_Free(pixels);pixels = NULL;
3404 mymiplevel = savemiplevel;
3405 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3407 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);
3408 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3409 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3414 mymiplevel = savemiplevel;
3415 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3417 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);
3418 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3419 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3424 mymiplevel = savemiplevel;
3425 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3427 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);
3428 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3429 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3434 mymiplevel = savemiplevel;
3435 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3437 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);
3438 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3439 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3445 Mem_Free(basepixels);
3450 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3451 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3454 unsigned char *temp1, *temp2;
3455 skinframe_t *skinframe;
3457 if (cls.state == ca_dedicated)
3460 // if already loaded just return it, otherwise make a new skinframe
3461 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3462 if (skinframe && skinframe->base)
3465 skinframe->stain = NULL;
3466 skinframe->merged = NULL;
3467 skinframe->base = NULL;
3468 skinframe->pants = NULL;
3469 skinframe->shirt = NULL;
3470 skinframe->nmap = NULL;
3471 skinframe->gloss = NULL;
3472 skinframe->glow = NULL;
3473 skinframe->fog = NULL;
3474 skinframe->reflect = NULL;
3475 skinframe->hasalpha = false;
3477 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3481 if (developer_loading.integer)
3482 Con_Printf("loading 32bit skin \"%s\"\n", name);
3484 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3486 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3487 temp2 = temp1 + width * height * 4;
3488 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3489 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);
3492 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3493 if (textureflags & TEXF_ALPHA)
3495 for (i = 3;i < width * height * 4;i += 4)
3497 if (skindata[i] < 255)
3499 skinframe->hasalpha = true;
3503 if (r_loadfog && skinframe->hasalpha)
3505 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3506 memcpy(fogpixels, skindata, width * height * 4);
3507 for (i = 0;i < width * height * 4;i += 4)
3508 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3509 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3510 Mem_Free(fogpixels);
3514 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3515 //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]);
3520 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3524 skinframe_t *skinframe;
3526 if (cls.state == ca_dedicated)
3529 // if already loaded just return it, otherwise make a new skinframe
3530 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3531 if (skinframe && skinframe->base)
3534 skinframe->stain = NULL;
3535 skinframe->merged = NULL;
3536 skinframe->base = NULL;
3537 skinframe->pants = NULL;
3538 skinframe->shirt = NULL;
3539 skinframe->nmap = NULL;
3540 skinframe->gloss = NULL;
3541 skinframe->glow = NULL;
3542 skinframe->fog = NULL;
3543 skinframe->reflect = NULL;
3544 skinframe->hasalpha = false;
3546 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3550 if (developer_loading.integer)
3551 Con_Printf("loading quake skin \"%s\"\n", name);
3553 // 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)
3554 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3555 memcpy(skinframe->qpixels, skindata, width*height);
3556 skinframe->qwidth = width;
3557 skinframe->qheight = height;
3560 for (i = 0;i < width * height;i++)
3561 featuresmask |= palette_featureflags[skindata[i]];
3563 skinframe->hasalpha = false;
3564 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3565 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3566 skinframe->qgeneratemerged = true;
3567 skinframe->qgeneratebase = skinframe->qhascolormapping;
3568 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3570 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3571 //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]);
3576 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3580 unsigned char *skindata;
3582 if (!skinframe->qpixels)
3585 if (!skinframe->qhascolormapping)
3586 colormapped = false;
3590 if (!skinframe->qgeneratebase)
3595 if (!skinframe->qgeneratemerged)
3599 width = skinframe->qwidth;
3600 height = skinframe->qheight;
3601 skindata = skinframe->qpixels;
3603 if (skinframe->qgeneratenmap)
3605 unsigned char *temp1, *temp2;
3606 skinframe->qgeneratenmap = false;
3607 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3608 temp2 = temp1 + width * height * 4;
3609 // use either a custom palette or the quake palette
3610 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3611 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3612 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);
3616 if (skinframe->qgenerateglow)
3618 skinframe->qgenerateglow = false;
3619 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
3624 skinframe->qgeneratebase = false;
3625 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);
3626 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);
3627 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);
3631 skinframe->qgeneratemerged = false;
3632 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);
3635 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3637 Mem_Free(skinframe->qpixels);
3638 skinframe->qpixels = NULL;
3642 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)
3645 skinframe_t *skinframe;
3647 if (cls.state == ca_dedicated)
3650 // if already loaded just return it, otherwise make a new skinframe
3651 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3652 if (skinframe && skinframe->base)
3655 skinframe->stain = NULL;
3656 skinframe->merged = NULL;
3657 skinframe->base = NULL;
3658 skinframe->pants = NULL;
3659 skinframe->shirt = NULL;
3660 skinframe->nmap = NULL;
3661 skinframe->gloss = NULL;
3662 skinframe->glow = NULL;
3663 skinframe->fog = NULL;
3664 skinframe->reflect = NULL;
3665 skinframe->hasalpha = false;
3667 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3671 if (developer_loading.integer)
3672 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3674 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3675 if (textureflags & TEXF_ALPHA)
3677 for (i = 0;i < width * height;i++)
3679 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3681 skinframe->hasalpha = true;
3685 if (r_loadfog && skinframe->hasalpha)
3686 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3689 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3690 //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]);
3695 skinframe_t *R_SkinFrame_LoadMissing(void)
3697 skinframe_t *skinframe;
3699 if (cls.state == ca_dedicated)
3702 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3703 skinframe->stain = NULL;
3704 skinframe->merged = NULL;
3705 skinframe->base = NULL;
3706 skinframe->pants = NULL;
3707 skinframe->shirt = NULL;
3708 skinframe->nmap = NULL;
3709 skinframe->gloss = NULL;
3710 skinframe->glow = NULL;
3711 skinframe->fog = NULL;
3712 skinframe->reflect = NULL;
3713 skinframe->hasalpha = false;
3715 skinframe->avgcolor[0] = rand() / RAND_MAX;
3716 skinframe->avgcolor[1] = rand() / RAND_MAX;
3717 skinframe->avgcolor[2] = rand() / RAND_MAX;
3718 skinframe->avgcolor[3] = 1;
3723 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3724 typedef struct suffixinfo_s
3727 qboolean flipx, flipy, flipdiagonal;
3730 static suffixinfo_t suffix[3][6] =
3733 {"px", false, false, false},
3734 {"nx", false, false, false},
3735 {"py", false, false, false},
3736 {"ny", false, false, false},
3737 {"pz", false, false, false},
3738 {"nz", false, false, false}
3741 {"posx", false, false, false},
3742 {"negx", false, false, false},
3743 {"posy", false, false, false},
3744 {"negy", false, false, false},
3745 {"posz", false, false, false},
3746 {"negz", false, false, false}
3749 {"rt", true, false, true},
3750 {"lf", false, true, true},
3751 {"ft", true, true, false},
3752 {"bk", false, false, false},
3753 {"up", true, false, true},
3754 {"dn", true, false, true}
3758 static int componentorder[4] = {0, 1, 2, 3};
3760 rtexture_t *R_LoadCubemap(const char *basename)
3762 int i, j, cubemapsize;
3763 unsigned char *cubemappixels, *image_buffer;
3764 rtexture_t *cubemaptexture;
3766 // must start 0 so the first loadimagepixels has no requested width/height
3768 cubemappixels = NULL;
3769 cubemaptexture = NULL;
3770 // keep trying different suffix groups (posx, px, rt) until one loads
3771 for (j = 0;j < 3 && !cubemappixels;j++)
3773 // load the 6 images in the suffix group
3774 for (i = 0;i < 6;i++)
3776 // generate an image name based on the base and and suffix
3777 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3779 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3781 // an image loaded, make sure width and height are equal
3782 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3784 // if this is the first image to load successfully, allocate the cubemap memory
3785 if (!cubemappixels && image_width >= 1)
3787 cubemapsize = image_width;
3788 // note this clears to black, so unavailable sides are black
3789 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3791 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3793 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);
3796 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3798 Mem_Free(image_buffer);
3802 // if a cubemap loaded, upload it
3805 if (developer_loading.integer)
3806 Con_Printf("loading cubemap \"%s\"\n", basename);
3808 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);
3809 Mem_Free(cubemappixels);
3813 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3814 if (developer_loading.integer)
3816 Con_Printf("(tried tried images ");
3817 for (j = 0;j < 3;j++)
3818 for (i = 0;i < 6;i++)
3819 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3820 Con_Print(" and was unable to find any of them).\n");
3823 return cubemaptexture;
3826 rtexture_t *R_GetCubemap(const char *basename)
3829 for (i = 0;i < r_texture_numcubemaps;i++)
3830 if (r_texture_cubemaps[i] != NULL)
3831 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3832 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3833 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3834 return r_texture_whitecube;
3835 r_texture_numcubemaps++;
3836 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3837 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3838 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3839 return r_texture_cubemaps[i]->texture;
3842 void R_FreeCubemap(const char *basename)
3846 for (i = 0;i < r_texture_numcubemaps;i++)
3848 if (r_texture_cubemaps[i] != NULL)
3850 if (r_texture_cubemaps[i]->texture)
3852 if (developer_loading.integer)
3853 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3854 R_FreeTexture(r_texture_cubemaps[i]->texture);
3855 Mem_Free(r_texture_cubemaps[i]);
3856 r_texture_cubemaps[i] = NULL;
3862 void R_FreeCubemaps(void)
3865 for (i = 0;i < r_texture_numcubemaps;i++)
3867 if (developer_loading.integer)
3868 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3869 if (r_texture_cubemaps[i] != NULL)
3871 if (r_texture_cubemaps[i]->texture)
3872 R_FreeTexture(r_texture_cubemaps[i]->texture);
3873 Mem_Free(r_texture_cubemaps[i]);
3876 r_texture_numcubemaps = 0;
3879 void R_Main_FreeViewCache(void)
3881 if (r_refdef.viewcache.entityvisible)
3882 Mem_Free(r_refdef.viewcache.entityvisible);
3883 if (r_refdef.viewcache.world_pvsbits)
3884 Mem_Free(r_refdef.viewcache.world_pvsbits);
3885 if (r_refdef.viewcache.world_leafvisible)
3886 Mem_Free(r_refdef.viewcache.world_leafvisible);
3887 if (r_refdef.viewcache.world_surfacevisible)
3888 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3889 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3892 void R_Main_ResizeViewCache(void)
3894 int numentities = r_refdef.scene.numentities;
3895 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3896 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3897 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3898 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3899 if (r_refdef.viewcache.maxentities < numentities)
3901 r_refdef.viewcache.maxentities = numentities;
3902 if (r_refdef.viewcache.entityvisible)
3903 Mem_Free(r_refdef.viewcache.entityvisible);
3904 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3906 if (r_refdef.viewcache.world_numclusters != numclusters)
3908 r_refdef.viewcache.world_numclusters = numclusters;
3909 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3910 if (r_refdef.viewcache.world_pvsbits)
3911 Mem_Free(r_refdef.viewcache.world_pvsbits);
3912 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3914 if (r_refdef.viewcache.world_numleafs != numleafs)
3916 r_refdef.viewcache.world_numleafs = numleafs;
3917 if (r_refdef.viewcache.world_leafvisible)
3918 Mem_Free(r_refdef.viewcache.world_leafvisible);
3919 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3921 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3923 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3924 if (r_refdef.viewcache.world_surfacevisible)
3925 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3926 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3930 extern rtexture_t *loadingscreentexture;
3931 void gl_main_start(void)
3933 loadingscreentexture = NULL;
3934 r_texture_blanknormalmap = NULL;
3935 r_texture_white = NULL;
3936 r_texture_grey128 = NULL;
3937 r_texture_black = NULL;
3938 r_texture_whitecube = NULL;
3939 r_texture_normalizationcube = NULL;
3940 r_texture_fogattenuation = NULL;
3941 r_texture_fogheighttexture = NULL;
3942 r_texture_gammaramps = NULL;
3943 r_texture_numcubemaps = 0;
3945 r_loaddds = r_texture_dds_load.integer != 0;
3946 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3948 switch(vid.renderpath)
3950 case RENDERPATH_GL20:
3951 case RENDERPATH_D3D9:
3952 case RENDERPATH_D3D10:
3953 case RENDERPATH_D3D11:
3954 case RENDERPATH_SOFT:
3955 case RENDERPATH_GLES2:
3956 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3957 Cvar_SetValueQuick(&gl_combine, 1);
3958 Cvar_SetValueQuick(&r_glsl, 1);
3959 r_loadnormalmap = true;
3963 case RENDERPATH_GL13:
3964 case RENDERPATH_GLES1:
3965 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3966 Cvar_SetValueQuick(&gl_combine, 1);
3967 Cvar_SetValueQuick(&r_glsl, 0);
3968 r_loadnormalmap = false;
3969 r_loadgloss = false;
3972 case RENDERPATH_GL11:
3973 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3974 Cvar_SetValueQuick(&gl_combine, 0);
3975 Cvar_SetValueQuick(&r_glsl, 0);
3976 r_loadnormalmap = false;
3977 r_loadgloss = false;
3983 R_FrameData_Reset();
3987 memset(r_queries, 0, sizeof(r_queries));
3989 r_qwskincache = NULL;
3990 r_qwskincache_size = 0;
3992 // due to caching of texture_t references, the collision cache must be reset
3993 Collision_Cache_Reset(true);
3995 // set up r_skinframe loading system for textures
3996 memset(&r_skinframe, 0, sizeof(r_skinframe));
3997 r_skinframe.loadsequence = 1;
3998 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4000 r_main_texturepool = R_AllocTexturePool();
4001 R_BuildBlankTextures();
4003 if (vid.support.arb_texture_cube_map)
4006 R_BuildNormalizationCube();
4008 r_texture_fogattenuation = NULL;
4009 r_texture_fogheighttexture = NULL;
4010 r_texture_gammaramps = NULL;
4011 //r_texture_fogintensity = NULL;
4012 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4013 memset(&r_waterstate, 0, sizeof(r_waterstate));
4014 r_glsl_permutation = NULL;
4015 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4016 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4017 glslshaderstring = NULL;
4019 r_hlsl_permutation = NULL;
4020 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4021 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4023 hlslshaderstring = NULL;
4024 memset(&r_svbsp, 0, sizeof (r_svbsp));
4026 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4027 r_texture_numcubemaps = 0;
4029 r_refdef.fogmasktable_density = 0;
4032 void gl_main_shutdown(void)
4035 R_FrameData_Reset();
4037 R_Main_FreeViewCache();
4039 switch(vid.renderpath)
4041 case RENDERPATH_GL11:
4042 case RENDERPATH_GL13:
4043 case RENDERPATH_GL20:
4044 case RENDERPATH_GLES1:
4045 case RENDERPATH_GLES2:
4047 qglDeleteQueriesARB(r_maxqueries, r_queries);
4049 case RENDERPATH_D3D9:
4050 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4052 case RENDERPATH_D3D10:
4053 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4055 case RENDERPATH_D3D11:
4056 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4058 case RENDERPATH_SOFT:
4064 memset(r_queries, 0, sizeof(r_queries));
4066 r_qwskincache = NULL;
4067 r_qwskincache_size = 0;
4069 // clear out the r_skinframe state
4070 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4071 memset(&r_skinframe, 0, sizeof(r_skinframe));
4074 Mem_Free(r_svbsp.nodes);
4075 memset(&r_svbsp, 0, sizeof (r_svbsp));
4076 R_FreeTexturePool(&r_main_texturepool);
4077 loadingscreentexture = NULL;
4078 r_texture_blanknormalmap = NULL;
4079 r_texture_white = NULL;
4080 r_texture_grey128 = NULL;
4081 r_texture_black = NULL;
4082 r_texture_whitecube = NULL;
4083 r_texture_normalizationcube = NULL;
4084 r_texture_fogattenuation = NULL;
4085 r_texture_fogheighttexture = NULL;
4086 r_texture_gammaramps = NULL;
4087 r_texture_numcubemaps = 0;
4088 //r_texture_fogintensity = NULL;
4089 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4090 memset(&r_waterstate, 0, sizeof(r_waterstate));
4093 r_glsl_permutation = NULL;
4094 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4095 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4096 glslshaderstring = NULL;
4098 r_hlsl_permutation = NULL;
4099 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4100 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4102 hlslshaderstring = NULL;
4105 extern void CL_ParseEntityLump(char *entitystring);
4106 void gl_main_newmap(void)
4108 // FIXME: move this code to client
4109 char *entities, entname[MAX_QPATH];
4111 Mem_Free(r_qwskincache);
4112 r_qwskincache = NULL;
4113 r_qwskincache_size = 0;
4116 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4117 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4119 CL_ParseEntityLump(entities);
4123 if (cl.worldmodel->brush.entities)
4124 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4126 R_Main_FreeViewCache();
4128 R_FrameData_Reset();
4131 void GL_Main_Init(void)
4133 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4135 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4136 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4137 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4138 if (gamemode == GAME_NEHAHRA)
4140 Cvar_RegisterVariable (&gl_fogenable);
4141 Cvar_RegisterVariable (&gl_fogdensity);
4142 Cvar_RegisterVariable (&gl_fogred);
4143 Cvar_RegisterVariable (&gl_foggreen);
4144 Cvar_RegisterVariable (&gl_fogblue);
4145 Cvar_RegisterVariable (&gl_fogstart);
4146 Cvar_RegisterVariable (&gl_fogend);
4147 Cvar_RegisterVariable (&gl_skyclip);
4149 Cvar_RegisterVariable(&r_motionblur);
4150 Cvar_RegisterVariable(&r_damageblur);
4151 Cvar_RegisterVariable(&r_motionblur_averaging);
4152 Cvar_RegisterVariable(&r_motionblur_randomize);
4153 Cvar_RegisterVariable(&r_motionblur_minblur);
4154 Cvar_RegisterVariable(&r_motionblur_maxblur);
4155 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4156 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4157 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4158 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4159 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4160 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4161 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4162 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4163 Cvar_RegisterVariable(&r_equalize_entities_by);
4164 Cvar_RegisterVariable(&r_equalize_entities_to);
4165 Cvar_RegisterVariable(&r_depthfirst);
4166 Cvar_RegisterVariable(&r_useinfinitefarclip);
4167 Cvar_RegisterVariable(&r_farclip_base);
4168 Cvar_RegisterVariable(&r_farclip_world);
4169 Cvar_RegisterVariable(&r_nearclip);
4170 Cvar_RegisterVariable(&r_deformvertexes);
4171 Cvar_RegisterVariable(&r_transparent);
4172 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4173 Cvar_RegisterVariable(&r_showoverdraw);
4174 Cvar_RegisterVariable(&r_showbboxes);
4175 Cvar_RegisterVariable(&r_showsurfaces);
4176 Cvar_RegisterVariable(&r_showtris);
4177 Cvar_RegisterVariable(&r_shownormals);
4178 Cvar_RegisterVariable(&r_showlighting);
4179 Cvar_RegisterVariable(&r_showshadowvolumes);
4180 Cvar_RegisterVariable(&r_showcollisionbrushes);
4181 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4182 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4183 Cvar_RegisterVariable(&r_showdisabledepthtest);
4184 Cvar_RegisterVariable(&r_drawportals);
4185 Cvar_RegisterVariable(&r_drawentities);
4186 Cvar_RegisterVariable(&r_draw2d);
4187 Cvar_RegisterVariable(&r_drawworld);
4188 Cvar_RegisterVariable(&r_cullentities_trace);
4189 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4190 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4191 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4192 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4193 Cvar_RegisterVariable(&r_drawviewmodel);
4194 Cvar_RegisterVariable(&r_drawexteriormodel);
4195 Cvar_RegisterVariable(&r_speeds);
4196 Cvar_RegisterVariable(&r_fullbrights);
4197 Cvar_RegisterVariable(&r_wateralpha);
4198 Cvar_RegisterVariable(&r_dynamic);
4199 Cvar_RegisterVariable(&r_fakelight);
4200 Cvar_RegisterVariable(&r_fakelight_intensity);
4201 Cvar_RegisterVariable(&r_fullbright);
4202 Cvar_RegisterVariable(&r_shadows);
4203 Cvar_RegisterVariable(&r_shadows_darken);
4204 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4205 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4206 Cvar_RegisterVariable(&r_shadows_throwdistance);
4207 Cvar_RegisterVariable(&r_shadows_throwdirection);
4208 Cvar_RegisterVariable(&r_shadows_focus);
4209 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4210 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4211 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4212 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4213 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4214 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4215 Cvar_RegisterVariable(&r_fog_exp2);
4216 Cvar_RegisterVariable(&r_fog_clear);
4217 Cvar_RegisterVariable(&r_drawfog);
4218 Cvar_RegisterVariable(&r_transparentdepthmasking);
4219 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4220 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4221 Cvar_RegisterVariable(&r_texture_dds_load);
4222 Cvar_RegisterVariable(&r_texture_dds_save);
4223 Cvar_RegisterVariable(&r_textureunits);
4224 Cvar_RegisterVariable(&gl_combine);
4225 Cvar_RegisterVariable(&r_viewfbo);
4226 Cvar_RegisterVariable(&r_viewscale);
4227 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4228 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4229 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4230 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4231 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4232 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4233 Cvar_RegisterVariable(&r_glsl);
4234 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4235 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4236 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4237 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4238 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4239 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4240 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4241 Cvar_RegisterVariable(&r_glsl_postprocess);
4242 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4243 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4244 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4245 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4246 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4247 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4248 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4249 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4251 Cvar_RegisterVariable(&r_water);
4252 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4253 Cvar_RegisterVariable(&r_water_clippingplanebias);
4254 Cvar_RegisterVariable(&r_water_refractdistort);
4255 Cvar_RegisterVariable(&r_water_reflectdistort);
4256 Cvar_RegisterVariable(&r_water_scissormode);
4257 Cvar_RegisterVariable(&r_water_lowquality);
4259 Cvar_RegisterVariable(&r_lerpsprites);
4260 Cvar_RegisterVariable(&r_lerpmodels);
4261 Cvar_RegisterVariable(&r_lerplightstyles);
4262 Cvar_RegisterVariable(&r_waterscroll);
4263 Cvar_RegisterVariable(&r_bloom);
4264 Cvar_RegisterVariable(&r_bloom_colorscale);
4265 Cvar_RegisterVariable(&r_bloom_brighten);
4266 Cvar_RegisterVariable(&r_bloom_blur);
4267 Cvar_RegisterVariable(&r_bloom_resolution);
4268 Cvar_RegisterVariable(&r_bloom_colorexponent);
4269 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4270 Cvar_RegisterVariable(&r_hdr);
4271 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4272 Cvar_RegisterVariable(&r_hdr_glowintensity);
4273 Cvar_RegisterVariable(&r_hdr_range);
4274 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4275 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4276 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4277 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4278 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4279 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4280 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4281 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4282 Cvar_RegisterVariable(&developer_texturelogging);
4283 Cvar_RegisterVariable(&gl_lightmaps);
4284 Cvar_RegisterVariable(&r_test);
4285 Cvar_RegisterVariable(&r_glsl_saturation);
4286 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4287 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4288 Cvar_RegisterVariable(&r_framedatasize);
4289 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4290 Cvar_SetValue("r_fullbrights", 0);
4291 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4294 extern void R_Textures_Init(void);
4295 extern void GL_Draw_Init(void);
4296 extern void GL_Main_Init(void);
4297 extern void R_Shadow_Init(void);
4298 extern void R_Sky_Init(void);
4299 extern void GL_Surf_Init(void);
4300 extern void R_Particles_Init(void);
4301 extern void R_Explosion_Init(void);
4302 extern void gl_backend_init(void);
4303 extern void Sbar_Init(void);
4304 extern void R_LightningBeams_Init(void);
4305 extern void Mod_RenderInit(void);
4306 extern void Font_Init(void);
4308 void Render_Init(void)
4321 R_LightningBeams_Init();
4330 extern char *ENGINE_EXTENSIONS;
4333 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4334 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4335 gl_version = (const char *)qglGetString(GL_VERSION);
4336 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4340 if (!gl_platformextensions)
4341 gl_platformextensions = "";
4343 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4344 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4345 Con_Printf("GL_VERSION: %s\n", gl_version);
4346 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4347 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4349 VID_CheckExtensions();
4351 // LordHavoc: report supported extensions
4352 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4354 // clear to black (loading plaque will be seen over this)
4355 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4358 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4362 if (r_trippy.integer)
4364 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4366 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4369 p = r_refdef.view.frustum + i;
4374 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4378 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4382 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4386 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4390 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4394 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4398 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4402 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4410 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4414 if (r_trippy.integer)
4416 for (i = 0;i < numplanes;i++)
4423 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4427 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4431 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4435 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4439 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4443 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4447 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4451 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4459 //==================================================================================
4461 // LordHavoc: this stores temporary data used within the same frame
4463 typedef struct r_framedata_mem_s
4465 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4466 size_t size; // how much usable space
4467 size_t current; // how much space in use
4468 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4469 size_t wantedsize; // how much space was allocated
4470 unsigned char *data; // start of real data (16byte aligned)
4474 static r_framedata_mem_t *r_framedata_mem;
4476 void R_FrameData_Reset(void)
4478 while (r_framedata_mem)
4480 r_framedata_mem_t *next = r_framedata_mem->purge;
4481 Mem_Free(r_framedata_mem);
4482 r_framedata_mem = next;
4486 void R_FrameData_Resize(void)
4489 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4490 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4491 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4493 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4494 newmem->wantedsize = wantedsize;
4495 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4496 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4497 newmem->current = 0;
4499 newmem->purge = r_framedata_mem;
4500 r_framedata_mem = newmem;
4504 void R_FrameData_NewFrame(void)
4506 R_FrameData_Resize();
4507 if (!r_framedata_mem)
4509 // if we ran out of space on the last frame, free the old memory now
4510 while (r_framedata_mem->purge)
4512 // repeatedly remove the second item in the list, leaving only head
4513 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4514 Mem_Free(r_framedata_mem->purge);
4515 r_framedata_mem->purge = next;
4517 // reset the current mem pointer
4518 r_framedata_mem->current = 0;
4519 r_framedata_mem->mark = 0;
4522 void *R_FrameData_Alloc(size_t size)
4526 // align to 16 byte boundary - the data pointer is already aligned, so we
4527 // only need to ensure the size of every allocation is also aligned
4528 size = (size + 15) & ~15;
4530 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4532 // emergency - we ran out of space, allocate more memory
4533 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4534 R_FrameData_Resize();
4537 data = r_framedata_mem->data + r_framedata_mem->current;
4538 r_framedata_mem->current += size;
4540 // count the usage for stats
4541 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4542 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4544 return (void *)data;
4547 void *R_FrameData_Store(size_t size, void *data)
4549 void *d = R_FrameData_Alloc(size);
4551 memcpy(d, data, size);
4555 void R_FrameData_SetMark(void)
4557 if (!r_framedata_mem)
4559 r_framedata_mem->mark = r_framedata_mem->current;
4562 void R_FrameData_ReturnToMark(void)
4564 if (!r_framedata_mem)
4566 r_framedata_mem->current = r_framedata_mem->mark;
4569 //==================================================================================
4571 // LordHavoc: animcache originally written by Echon, rewritten since then
4574 * Animation cache prevents re-generating mesh data for an animated model
4575 * multiple times in one frame for lighting, shadowing, reflections, etc.
4578 void R_AnimCache_Free(void)
4582 void R_AnimCache_ClearCache(void)
4585 entity_render_t *ent;
4587 for (i = 0;i < r_refdef.scene.numentities;i++)
4589 ent = r_refdef.scene.entities[i];
4590 ent->animcache_vertex3f = NULL;
4591 ent->animcache_normal3f = NULL;
4592 ent->animcache_svector3f = NULL;
4593 ent->animcache_tvector3f = NULL;
4594 ent->animcache_vertexmesh = NULL;
4595 ent->animcache_vertex3fbuffer = NULL;
4596 ent->animcache_vertexmeshbuffer = NULL;
4600 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4604 // check if we need the meshbuffers
4605 if (!vid.useinterleavedarrays)
4608 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4609 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4610 // TODO: upload vertex3f buffer?
4611 if (ent->animcache_vertexmesh)
4613 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4614 for (i = 0;i < numvertices;i++)
4615 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4616 if (ent->animcache_svector3f)
4617 for (i = 0;i < numvertices;i++)
4618 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4619 if (ent->animcache_tvector3f)
4620 for (i = 0;i < numvertices;i++)
4621 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4622 if (ent->animcache_normal3f)
4623 for (i = 0;i < numvertices;i++)
4624 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4625 // TODO: upload vertexmeshbuffer?
4629 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4631 dp_model_t *model = ent->model;
4633 // see if it's already cached this frame
4634 if (ent->animcache_vertex3f)
4636 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4637 if (wantnormals || wanttangents)
4639 if (ent->animcache_normal3f)
4640 wantnormals = false;
4641 if (ent->animcache_svector3f)
4642 wanttangents = false;
4643 if (wantnormals || wanttangents)
4645 numvertices = model->surfmesh.num_vertices;
4647 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4650 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4651 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4653 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4654 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4660 // see if this ent is worth caching
4661 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4663 // get some memory for this entity and generate mesh data
4664 numvertices = model->surfmesh.num_vertices;
4665 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4667 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4670 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4671 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4673 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4674 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4679 void R_AnimCache_CacheVisibleEntities(void)
4682 qboolean wantnormals = true;
4683 qboolean wanttangents = !r_showsurfaces.integer;
4685 switch(vid.renderpath)
4687 case RENDERPATH_GL20:
4688 case RENDERPATH_D3D9:
4689 case RENDERPATH_D3D10:
4690 case RENDERPATH_D3D11:
4691 case RENDERPATH_GLES2:
4693 case RENDERPATH_GL11:
4694 case RENDERPATH_GL13:
4695 case RENDERPATH_GLES1:
4696 wanttangents = false;
4698 case RENDERPATH_SOFT:
4702 if (r_shownormals.integer)
4703 wanttangents = wantnormals = true;
4705 // TODO: thread this
4706 // NOTE: R_PrepareRTLights() also caches entities
4708 for (i = 0;i < r_refdef.scene.numentities;i++)
4709 if (r_refdef.viewcache.entityvisible[i])
4710 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4713 //==================================================================================
4715 extern cvar_t r_overheadsprites_pushback;
4717 static void R_View_UpdateEntityLighting (void)
4720 entity_render_t *ent;
4721 vec3_t tempdiffusenormal, avg;
4722 vec_t f, fa, fd, fdd;
4723 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4725 for (i = 0;i < r_refdef.scene.numentities;i++)
4727 ent = r_refdef.scene.entities[i];
4729 // skip unseen models
4730 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4734 if (ent->model && ent->model->brush.num_leafs)
4736 // TODO: use modellight for r_ambient settings on world?
4737 VectorSet(ent->modellight_ambient, 0, 0, 0);
4738 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4739 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4743 // fetch the lighting from the worldmodel data
4744 VectorClear(ent->modellight_ambient);
4745 VectorClear(ent->modellight_diffuse);
4746 VectorClear(tempdiffusenormal);
4747 if (ent->flags & RENDER_LIGHT)
4750 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4752 // complete lightning for lit sprites
4753 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4754 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4756 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4757 org[2] = org[2] + r_overheadsprites_pushback.value;
4758 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4761 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4763 if(ent->flags & RENDER_EQUALIZE)
4765 // first fix up ambient lighting...
4766 if(r_equalize_entities_minambient.value > 0)
4768 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4771 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4772 if(fa < r_equalize_entities_minambient.value * fd)
4775 // fa'/fd' = minambient
4776 // fa'+0.25*fd' = fa+0.25*fd
4778 // fa' = fd' * minambient
4779 // fd'*(0.25+minambient) = fa+0.25*fd
4781 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4782 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4784 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4785 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
4786 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4787 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4792 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4794 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4795 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4799 // adjust brightness and saturation to target
4800 avg[0] = avg[1] = avg[2] = fa / f;
4801 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4802 avg[0] = avg[1] = avg[2] = fd / f;
4803 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4809 VectorSet(ent->modellight_ambient, 1, 1, 1);
4811 // move the light direction into modelspace coordinates for lighting code
4812 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4813 if(VectorLength2(ent->modellight_lightdir) == 0)
4814 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4815 VectorNormalize(ent->modellight_lightdir);
4819 #define MAX_LINEOFSIGHTTRACES 64
4821 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4824 vec3_t boxmins, boxmaxs;
4827 dp_model_t *model = r_refdef.scene.worldmodel;
4829 if (!model || !model->brush.TraceLineOfSight)
4832 // expand the box a little
4833 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4834 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4835 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4836 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4837 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4838 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4840 // return true if eye is inside enlarged box
4841 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4845 VectorCopy(eye, start);
4846 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4847 if (model->brush.TraceLineOfSight(model, start, end))
4850 // try various random positions
4851 for (i = 0;i < numsamples;i++)
4853 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4854 if (model->brush.TraceLineOfSight(model, start, end))
4862 static void R_View_UpdateEntityVisible (void)
4867 entity_render_t *ent;
4869 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4870 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4871 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4872 : RENDER_EXTERIORMODEL;
4873 if (!r_drawviewmodel.integer)
4874 renderimask |= RENDER_VIEWMODEL;
4875 if (!r_drawexteriormodel.integer)
4876 renderimask |= RENDER_EXTERIORMODEL;
4877 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4879 // worldmodel can check visibility
4880 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4881 for (i = 0;i < r_refdef.scene.numentities;i++)
4883 ent = r_refdef.scene.entities[i];
4884 if (!(ent->flags & renderimask))
4885 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)))
4886 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))
4887 r_refdef.viewcache.entityvisible[i] = true;
4892 // no worldmodel or it can't check visibility
4893 for (i = 0;i < r_refdef.scene.numentities;i++)
4895 ent = r_refdef.scene.entities[i];
4896 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));
4899 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4900 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4902 for (i = 0;i < r_refdef.scene.numentities;i++)
4904 if (!r_refdef.viewcache.entityvisible[i])
4906 ent = r_refdef.scene.entities[i];
4907 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4909 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4911 continue; // temp entities do pvs only
4912 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4913 ent->last_trace_visibility = realtime;
4914 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4915 r_refdef.viewcache.entityvisible[i] = 0;
4921 /// only used if skyrendermasked, and normally returns false
4922 int R_DrawBrushModelsSky (void)
4925 entity_render_t *ent;
4928 for (i = 0;i < r_refdef.scene.numentities;i++)
4930 if (!r_refdef.viewcache.entityvisible[i])
4932 ent = r_refdef.scene.entities[i];
4933 if (!ent->model || !ent->model->DrawSky)
4935 ent->model->DrawSky(ent);
4941 static void R_DrawNoModel(entity_render_t *ent);
4942 static void R_DrawModels(void)
4945 entity_render_t *ent;
4947 for (i = 0;i < r_refdef.scene.numentities;i++)
4949 if (!r_refdef.viewcache.entityvisible[i])
4951 ent = r_refdef.scene.entities[i];
4952 r_refdef.stats.entities++;
4954 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4957 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4958 Con_Printf("R_DrawModels\n");
4959 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]);
4960 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);
4961 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);
4964 if (ent->model && ent->model->Draw != NULL)
4965 ent->model->Draw(ent);
4971 static void R_DrawModelsDepth(void)
4974 entity_render_t *ent;
4976 for (i = 0;i < r_refdef.scene.numentities;i++)
4978 if (!r_refdef.viewcache.entityvisible[i])
4980 ent = r_refdef.scene.entities[i];
4981 if (ent->model && ent->model->DrawDepth != NULL)
4982 ent->model->DrawDepth(ent);
4986 static void R_DrawModelsDebug(void)
4989 entity_render_t *ent;
4991 for (i = 0;i < r_refdef.scene.numentities;i++)
4993 if (!r_refdef.viewcache.entityvisible[i])
4995 ent = r_refdef.scene.entities[i];
4996 if (ent->model && ent->model->DrawDebug != NULL)
4997 ent->model->DrawDebug(ent);
5001 static void R_DrawModelsAddWaterPlanes(void)
5004 entity_render_t *ent;
5006 for (i = 0;i < r_refdef.scene.numentities;i++)
5008 if (!r_refdef.viewcache.entityvisible[i])
5010 ent = r_refdef.scene.entities[i];
5011 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5012 ent->model->DrawAddWaterPlanes(ent);
5016 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5018 if (r_hdr_irisadaptation.integer)
5022 vec3_t diffusenormal;
5026 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5027 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5028 brightness = max(0.0000001f, brightness);
5029 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5030 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5031 current = r_hdr_irisadaptation_value.value;
5033 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5034 else if (current > goal)
5035 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5036 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5037 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5039 else if (r_hdr_irisadaptation_value.value != 1.0f)
5040 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5043 static void R_View_SetFrustum(const int *scissor)
5046 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5047 vec3_t forward, left, up, origin, v;
5051 // flipped x coordinates (because x points left here)
5052 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5053 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5055 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5056 switch(vid.renderpath)
5058 case RENDERPATH_D3D9:
5059 case RENDERPATH_D3D10:
5060 case RENDERPATH_D3D11:
5061 // non-flipped y coordinates
5062 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5063 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5065 case RENDERPATH_SOFT:
5066 case RENDERPATH_GL11:
5067 case RENDERPATH_GL13:
5068 case RENDERPATH_GL20:
5069 case RENDERPATH_GLES1:
5070 case RENDERPATH_GLES2:
5071 // non-flipped y coordinates
5072 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5073 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5078 // we can't trust r_refdef.view.forward and friends in reflected scenes
5079 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5082 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5083 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5084 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5085 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5086 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5087 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5088 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5089 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5090 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5091 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5092 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5093 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5097 zNear = r_refdef.nearclip;
5098 nudge = 1.0 - 1.0 / (1<<23);
5099 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5100 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5101 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5102 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5103 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5104 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5105 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5106 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5112 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5113 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5114 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5115 r_refdef.view.frustum[0].dist = m[15] - m[12];
5117 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5118 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5119 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5120 r_refdef.view.frustum[1].dist = m[15] + m[12];
5122 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5123 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5124 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5125 r_refdef.view.frustum[2].dist = m[15] - m[13];
5127 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5128 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5129 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5130 r_refdef.view.frustum[3].dist = m[15] + m[13];
5132 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5133 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5134 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5135 r_refdef.view.frustum[4].dist = m[15] - m[14];
5137 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5138 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5139 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5140 r_refdef.view.frustum[5].dist = m[15] + m[14];
5143 if (r_refdef.view.useperspective)
5145 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5146 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]);
5147 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]);
5148 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]);
5149 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]);
5151 // then the normals from the corners relative to origin
5152 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5153 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5154 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5155 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5157 // in a NORMAL view, forward cross left == up
5158 // in a REFLECTED view, forward cross left == down
5159 // so our cross products above need to be adjusted for a left handed coordinate system
5160 CrossProduct(forward, left, v);
5161 if(DotProduct(v, up) < 0)
5163 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5164 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5165 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5166 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5169 // Leaving those out was a mistake, those were in the old code, and they
5170 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5171 // I couldn't reproduce it after adding those normalizations. --blub
5172 VectorNormalize(r_refdef.view.frustum[0].normal);
5173 VectorNormalize(r_refdef.view.frustum[1].normal);
5174 VectorNormalize(r_refdef.view.frustum[2].normal);
5175 VectorNormalize(r_refdef.view.frustum[3].normal);
5177 // make the corners absolute
5178 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5179 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5180 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5181 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5184 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5186 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5187 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5188 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5189 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5190 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5194 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5195 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5196 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5197 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5198 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5199 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5200 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5201 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5202 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5203 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5205 r_refdef.view.numfrustumplanes = 5;
5207 if (r_refdef.view.useclipplane)
5209 r_refdef.view.numfrustumplanes = 6;
5210 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5213 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5214 PlaneClassify(r_refdef.view.frustum + i);
5216 // LordHavoc: note to all quake engine coders, Quake had a special case
5217 // for 90 degrees which assumed a square view (wrong), so I removed it,
5218 // Quake2 has it disabled as well.
5220 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5221 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5222 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5223 //PlaneClassify(&frustum[0]);
5225 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5226 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5227 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5228 //PlaneClassify(&frustum[1]);
5230 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5231 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5232 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5233 //PlaneClassify(&frustum[2]);
5235 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5236 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5237 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5238 //PlaneClassify(&frustum[3]);
5241 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5242 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5243 //PlaneClassify(&frustum[4]);
5246 void R_View_UpdateWithScissor(const int *myscissor)
5248 R_Main_ResizeViewCache();
5249 R_View_SetFrustum(myscissor);
5250 R_View_WorldVisibility(r_refdef.view.useclipplane);
5251 R_View_UpdateEntityVisible();
5252 R_View_UpdateEntityLighting();
5255 void R_View_Update(void)
5257 R_Main_ResizeViewCache();
5258 R_View_SetFrustum(NULL);
5259 R_View_WorldVisibility(r_refdef.view.useclipplane);
5260 R_View_UpdateEntityVisible();
5261 R_View_UpdateEntityLighting();
5264 float viewscalefpsadjusted = 1.0f;
5266 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5268 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5269 scale = bound(0.03125f, scale, 1.0f);
5270 *outwidth = (int)ceil(width * scale);
5271 *outheight = (int)ceil(height * scale);
5274 void R_Mesh_SetMainRenderTargets(void)
5276 if (r_bloomstate.fbo_framebuffer)
5277 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5279 R_Mesh_ResetRenderTargets();
5282 void R_SetupView(qboolean allowwaterclippingplane)
5284 const float *customclipplane = NULL;
5286 int scaledwidth, scaledheight;
5287 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5289 // LordHavoc: couldn't figure out how to make this approach the
5290 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5291 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5292 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5293 dist = r_refdef.view.clipplane.dist;
5294 plane[0] = r_refdef.view.clipplane.normal[0];
5295 plane[1] = r_refdef.view.clipplane.normal[1];
5296 plane[2] = r_refdef.view.clipplane.normal[2];
5298 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5301 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5302 if (!r_refdef.view.useperspective)
5303 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);
5304 else if (vid.stencil && r_useinfinitefarclip.integer)
5305 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);
5307 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);
5308 R_Mesh_SetMainRenderTargets();
5309 R_SetViewport(&r_refdef.view.viewport);
5310 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5312 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5313 float screenplane[4];
5314 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5315 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5316 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5317 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5318 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5322 void R_EntityMatrix(const matrix4x4_t *matrix)
5324 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5326 gl_modelmatrixchanged = false;
5327 gl_modelmatrix = *matrix;
5328 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5329 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5330 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5331 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5333 switch(vid.renderpath)
5335 case RENDERPATH_D3D9:
5337 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5338 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5341 case RENDERPATH_D3D10:
5342 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5344 case RENDERPATH_D3D11:
5345 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5347 case RENDERPATH_GL11:
5348 case RENDERPATH_GL13:
5349 case RENDERPATH_GLES1:
5350 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5352 case RENDERPATH_SOFT:
5353 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5354 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5356 case RENDERPATH_GL20:
5357 case RENDERPATH_GLES2:
5358 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5359 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5365 void R_ResetViewRendering2D(void)
5367 r_viewport_t viewport;
5370 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5371 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);
5372 R_Mesh_ResetRenderTargets();
5373 R_SetViewport(&viewport);
5374 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5375 GL_Color(1, 1, 1, 1);
5376 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5377 GL_BlendFunc(GL_ONE, GL_ZERO);
5378 GL_ScissorTest(false);
5379 GL_DepthMask(false);
5380 GL_DepthRange(0, 1);
5381 GL_DepthTest(false);
5382 GL_DepthFunc(GL_LEQUAL);
5383 R_EntityMatrix(&identitymatrix);
5384 R_Mesh_ResetTextureState();
5385 GL_PolygonOffset(0, 0);
5386 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5387 switch(vid.renderpath)
5389 case RENDERPATH_GL11:
5390 case RENDERPATH_GL13:
5391 case RENDERPATH_GL20:
5392 case RENDERPATH_GLES1:
5393 case RENDERPATH_GLES2:
5394 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5396 case RENDERPATH_D3D9:
5397 case RENDERPATH_D3D10:
5398 case RENDERPATH_D3D11:
5399 case RENDERPATH_SOFT:
5402 GL_CullFace(GL_NONE);
5405 void R_ResetViewRendering3D(void)
5410 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5411 GL_Color(1, 1, 1, 1);
5412 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5413 GL_BlendFunc(GL_ONE, GL_ZERO);
5414 GL_ScissorTest(true);
5416 GL_DepthRange(0, 1);
5418 GL_DepthFunc(GL_LEQUAL);
5419 R_EntityMatrix(&identitymatrix);
5420 R_Mesh_ResetTextureState();
5421 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5422 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5423 switch(vid.renderpath)
5425 case RENDERPATH_GL11:
5426 case RENDERPATH_GL13:
5427 case RENDERPATH_GL20:
5428 case RENDERPATH_GLES1:
5429 case RENDERPATH_GLES2:
5430 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5432 case RENDERPATH_D3D9:
5433 case RENDERPATH_D3D10:
5434 case RENDERPATH_D3D11:
5435 case RENDERPATH_SOFT:
5438 GL_CullFace(r_refdef.view.cullface_back);
5443 R_RenderView_UpdateViewVectors
5446 static void R_RenderView_UpdateViewVectors(void)
5448 // break apart the view matrix into vectors for various purposes
5449 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5450 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5451 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5452 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5453 // make an inverted copy of the view matrix for tracking sprites
5454 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5457 void R_RenderScene(void);
5458 void R_RenderWaterPlanes(void);
5460 static void R_Water_StartFrame(void)
5463 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5464 r_waterstate_waterplane_t *p;
5466 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5469 switch(vid.renderpath)
5471 case RENDERPATH_GL20:
5472 case RENDERPATH_D3D9:
5473 case RENDERPATH_D3D10:
5474 case RENDERPATH_D3D11:
5475 case RENDERPATH_SOFT:
5476 case RENDERPATH_GLES2:
5478 case RENDERPATH_GL11:
5479 case RENDERPATH_GL13:
5480 case RENDERPATH_GLES1:
5484 // set waterwidth and waterheight to the water resolution that will be
5485 // used (often less than the screen resolution for faster rendering)
5486 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5488 // calculate desired texture sizes
5489 // can't use water if the card does not support the texture size
5490 if (!r_water.integer || r_showsurfaces.integer)
5491 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5492 else if (vid.support.arb_texture_non_power_of_two)
5494 texturewidth = waterwidth;
5495 textureheight = waterheight;
5496 camerawidth = waterwidth;
5497 cameraheight = waterheight;
5501 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5502 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5503 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5504 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5507 // allocate textures as needed
5508 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5510 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5511 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5513 if (p->texture_refraction)
5514 R_FreeTexture(p->texture_refraction);
5515 p->texture_refraction = NULL;
5516 if (p->texture_reflection)
5517 R_FreeTexture(p->texture_reflection);
5518 p->texture_reflection = NULL;
5519 if (p->texture_camera)
5520 R_FreeTexture(p->texture_camera);
5521 p->texture_camera = NULL;
5523 memset(&r_waterstate, 0, sizeof(r_waterstate));
5524 r_waterstate.texturewidth = texturewidth;
5525 r_waterstate.textureheight = textureheight;
5526 r_waterstate.camerawidth = camerawidth;
5527 r_waterstate.cameraheight = cameraheight;
5530 if (r_waterstate.texturewidth)
5532 int scaledwidth, scaledheight;
5534 r_waterstate.enabled = true;
5536 // when doing a reduced render (HDR) we want to use a smaller area
5537 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5538 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5539 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5541 // set up variables that will be used in shader setup
5542 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5543 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5544 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5545 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5548 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5549 r_waterstate.numwaterplanes = 0;
5552 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5554 int triangleindex, planeindex;
5560 r_waterstate_waterplane_t *p;
5561 texture_t *t = R_GetCurrentTexture(surface->texture);
5563 // just use the first triangle with a valid normal for any decisions
5564 VectorClear(normal);
5565 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5567 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5568 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5569 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5570 TriangleNormal(vert[0], vert[1], vert[2], normal);
5571 if (VectorLength2(normal) >= 0.001)
5575 VectorCopy(normal, plane.normal);
5576 VectorNormalize(plane.normal);
5577 plane.dist = DotProduct(vert[0], plane.normal);
5578 PlaneClassify(&plane);
5579 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5581 // skip backfaces (except if nocullface is set)
5582 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5584 VectorNegate(plane.normal, plane.normal);
5586 PlaneClassify(&plane);
5590 // find a matching plane if there is one
5591 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5592 if(p->camera_entity == t->camera_entity)
5593 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5595 if (planeindex >= r_waterstate.maxwaterplanes)
5596 return; // nothing we can do, out of planes
5598 // if this triangle does not fit any known plane rendered this frame, add one
5599 if (planeindex >= r_waterstate.numwaterplanes)
5601 // store the new plane
5602 r_waterstate.numwaterplanes++;
5604 // clear materialflags and pvs
5605 p->materialflags = 0;
5606 p->pvsvalid = false;
5607 p->camera_entity = t->camera_entity;
5608 VectorCopy(surface->mins, p->mins);
5609 VectorCopy(surface->maxs, p->maxs);
5614 p->mins[0] = min(p->mins[0], surface->mins[0]);
5615 p->mins[1] = min(p->mins[1], surface->mins[1]);
5616 p->mins[2] = min(p->mins[2], surface->mins[2]);
5617 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5618 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5619 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5621 // merge this surface's materialflags into the waterplane
5622 p->materialflags |= t->currentmaterialflags;
5623 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5625 // merge this surface's PVS into the waterplane
5626 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5627 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5628 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5630 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5636 extern cvar_t r_drawparticles;
5637 extern cvar_t r_drawdecals;
5639 static void R_Water_ProcessPlanes(void)
5642 r_refdef_view_t originalview;
5643 r_refdef_view_t myview;
5644 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;
5645 r_waterstate_waterplane_t *p;
5648 originalview = r_refdef.view;
5650 // lowquality hack, temporarily shut down some cvars and restore afterwards
5651 qualityreduction = r_water_lowquality.integer;
5652 if (qualityreduction > 0)
5654 if (qualityreduction >= 1)
5656 old_r_shadows = r_shadows.integer;
5657 old_r_worldrtlight = r_shadow_realtime_world.integer;
5658 old_r_dlight = r_shadow_realtime_dlight.integer;
5659 Cvar_SetValueQuick(&r_shadows, 0);
5660 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5661 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5663 if (qualityreduction >= 2)
5665 old_r_dynamic = r_dynamic.integer;
5666 old_r_particles = r_drawparticles.integer;
5667 old_r_decals = r_drawdecals.integer;
5668 Cvar_SetValueQuick(&r_dynamic, 0);
5669 Cvar_SetValueQuick(&r_drawparticles, 0);
5670 Cvar_SetValueQuick(&r_drawdecals, 0);
5674 // make sure enough textures are allocated
5675 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5677 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5679 if (!p->texture_refraction)
5680 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);
5681 if (!p->texture_refraction)
5684 else if (p->materialflags & MATERIALFLAG_CAMERA)
5686 if (!p->texture_camera)
5687 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);
5688 if (!p->texture_camera)
5692 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5694 if (!p->texture_reflection)
5695 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);
5696 if (!p->texture_reflection)
5702 r_refdef.view = originalview;
5703 r_refdef.view.showdebug = false;
5704 r_refdef.view.width = r_waterstate.waterwidth;
5705 r_refdef.view.height = r_waterstate.waterheight;
5706 r_refdef.view.useclipplane = true;
5707 myview = r_refdef.view;
5708 r_waterstate.renderingscene = true;
5709 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5711 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5713 r_refdef.view = myview;
5714 if(r_water_scissormode.integer)
5717 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5718 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5721 // render reflected scene and copy into texture
5722 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5723 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5724 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5725 r_refdef.view.clipplane = p->plane;
5726 // reverse the cullface settings for this render
5727 r_refdef.view.cullface_front = GL_FRONT;
5728 r_refdef.view.cullface_back = GL_BACK;
5729 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5731 r_refdef.view.usecustompvs = true;
5733 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5735 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5738 R_ResetViewRendering3D();
5739 R_ClearScreen(r_refdef.fogenabled);
5740 if(r_water_scissormode.integer & 2)
5741 R_View_UpdateWithScissor(myscissor);
5744 if(r_water_scissormode.integer & 1)
5745 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5748 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);
5751 // render the normal view scene and copy into texture
5752 // (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)
5753 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5755 r_refdef.view = myview;
5756 if(r_water_scissormode.integer)
5759 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5760 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5763 r_waterstate.renderingrefraction = true;
5765 r_refdef.view.clipplane = p->plane;
5766 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5767 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5769 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5771 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5772 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5773 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5774 R_RenderView_UpdateViewVectors();
5775 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5777 r_refdef.view.usecustompvs = true;
5778 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);
5782 PlaneClassify(&r_refdef.view.clipplane);
5784 R_ResetViewRendering3D();
5785 R_ClearScreen(r_refdef.fogenabled);
5786 if(r_water_scissormode.integer & 2)
5787 R_View_UpdateWithScissor(myscissor);
5790 if(r_water_scissormode.integer & 1)
5791 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5794 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);
5795 r_waterstate.renderingrefraction = false;
5797 else if (p->materialflags & MATERIALFLAG_CAMERA)
5799 r_refdef.view = myview;
5801 r_refdef.view.clipplane = p->plane;
5802 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5803 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5805 r_refdef.view.width = r_waterstate.camerawidth;
5806 r_refdef.view.height = r_waterstate.cameraheight;
5807 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5808 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5810 if(p->camera_entity)
5812 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5813 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5816 // note: all of the view is used for displaying... so
5817 // there is no use in scissoring
5819 // reverse the cullface settings for this render
5820 r_refdef.view.cullface_front = GL_FRONT;
5821 r_refdef.view.cullface_back = GL_BACK;
5822 // also reverse the view matrix
5823 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
5824 R_RenderView_UpdateViewVectors();
5825 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5827 r_refdef.view.usecustompvs = true;
5828 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);
5831 // camera needs no clipplane
5832 r_refdef.view.useclipplane = false;
5834 PlaneClassify(&r_refdef.view.clipplane);
5836 R_ResetViewRendering3D();
5837 R_ClearScreen(r_refdef.fogenabled);
5841 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);
5842 r_waterstate.renderingrefraction = false;
5846 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5847 r_waterstate.renderingscene = false;
5848 r_refdef.view = originalview;
5849 R_ResetViewRendering3D();
5850 R_ClearScreen(r_refdef.fogenabled);
5854 r_refdef.view = originalview;
5855 r_waterstate.renderingscene = false;
5856 Cvar_SetValueQuick(&r_water, 0);
5857 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5859 // lowquality hack, restore cvars
5860 if (qualityreduction > 0)
5862 if (qualityreduction >= 1)
5864 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5865 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5866 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5868 if (qualityreduction >= 2)
5870 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5871 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5872 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5877 void R_Bloom_StartFrame(void)
5879 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5880 int viewwidth, viewheight;
5883 if (r_viewscale_fpsscaling.integer)
5885 double actualframetime;
5886 double targetframetime;
5888 actualframetime = r_refdef.lastdrawscreentime;
5889 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5890 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5891 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5892 if (r_viewscale_fpsscaling_stepsize.value > 0)
5893 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5894 viewscalefpsadjusted += adjust;
5895 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5898 viewscalefpsadjusted = 1.0f;
5900 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5902 switch(vid.renderpath)
5904 case RENDERPATH_GL20:
5905 case RENDERPATH_D3D9:
5906 case RENDERPATH_D3D10:
5907 case RENDERPATH_D3D11:
5908 case RENDERPATH_SOFT:
5909 case RENDERPATH_GLES2:
5911 case RENDERPATH_GL11:
5912 case RENDERPATH_GL13:
5913 case RENDERPATH_GLES1:
5917 // set bloomwidth and bloomheight to the bloom resolution that will be
5918 // used (often less than the screen resolution for faster rendering)
5919 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5920 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5921 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5922 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5923 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5925 // calculate desired texture sizes
5926 if (vid.support.arb_texture_non_power_of_two)
5928 screentexturewidth = vid.width;
5929 screentextureheight = vid.height;
5930 bloomtexturewidth = r_bloomstate.bloomwidth;
5931 bloomtextureheight = r_bloomstate.bloomheight;
5935 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5936 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5937 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5938 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5941 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))
5943 Cvar_SetValueQuick(&r_hdr, 0);
5944 Cvar_SetValueQuick(&r_bloom, 0);
5945 Cvar_SetValueQuick(&r_motionblur, 0);
5946 Cvar_SetValueQuick(&r_damageblur, 0);
5949 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)
5950 screentexturewidth = screentextureheight = 0;
5951 if (!r_hdr.integer && !r_bloom.integer)
5952 bloomtexturewidth = bloomtextureheight = 0;
5954 textype = TEXTYPE_COLORBUFFER;
5955 switch (vid.renderpath)
5957 case RENDERPATH_GL20:
5958 case RENDERPATH_GLES2:
5959 if (vid.support.ext_framebuffer_object)
5961 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5962 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5965 case RENDERPATH_GL11:
5966 case RENDERPATH_GL13:
5967 case RENDERPATH_GLES1:
5968 case RENDERPATH_D3D9:
5969 case RENDERPATH_D3D10:
5970 case RENDERPATH_D3D11:
5971 case RENDERPATH_SOFT:
5975 // allocate textures as needed
5976 if (r_bloomstate.screentexturewidth != screentexturewidth
5977 || r_bloomstate.screentextureheight != screentextureheight
5978 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5979 || r_bloomstate.bloomtextureheight != bloomtextureheight
5980 || r_bloomstate.texturetype != textype
5981 || r_bloomstate.viewfbo != r_viewfbo.integer)
5983 if (r_bloomstate.texture_bloom)
5984 R_FreeTexture(r_bloomstate.texture_bloom);
5985 r_bloomstate.texture_bloom = NULL;
5986 if (r_bloomstate.texture_screen)
5987 R_FreeTexture(r_bloomstate.texture_screen);
5988 r_bloomstate.texture_screen = NULL;
5989 if (r_bloomstate.fbo_framebuffer)
5990 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5991 r_bloomstate.fbo_framebuffer = 0;
5992 if (r_bloomstate.texture_framebuffercolor)
5993 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5994 r_bloomstate.texture_framebuffercolor = NULL;
5995 if (r_bloomstate.texture_framebufferdepth)
5996 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5997 r_bloomstate.texture_framebufferdepth = NULL;
5998 r_bloomstate.screentexturewidth = screentexturewidth;
5999 r_bloomstate.screentextureheight = screentextureheight;
6000 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6001 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);
6002 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6004 // FIXME: choose depth bits based on a cvar
6005 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6006 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);
6007 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6008 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6009 // render depth into one texture and normalmap into the other
6013 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6014 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6015 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6016 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6017 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6020 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6021 r_bloomstate.bloomtextureheight = bloomtextureheight;
6022 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6023 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);
6024 r_bloomstate.viewfbo = r_viewfbo.integer;
6025 r_bloomstate.texturetype = textype;
6028 // when doing a reduced render (HDR) we want to use a smaller area
6029 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6030 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6031 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6032 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6033 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6035 // set up a texcoord array for the full resolution screen image
6036 // (we have to keep this around to copy back during final render)
6037 r_bloomstate.screentexcoord2f[0] = 0;
6038 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6039 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6040 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6041 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6042 r_bloomstate.screentexcoord2f[5] = 0;
6043 r_bloomstate.screentexcoord2f[6] = 0;
6044 r_bloomstate.screentexcoord2f[7] = 0;
6046 // set up a texcoord array for the reduced resolution bloom image
6047 // (which will be additive blended over the screen image)
6048 r_bloomstate.bloomtexcoord2f[0] = 0;
6049 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6050 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6051 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6052 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6053 r_bloomstate.bloomtexcoord2f[5] = 0;
6054 r_bloomstate.bloomtexcoord2f[6] = 0;
6055 r_bloomstate.bloomtexcoord2f[7] = 0;
6057 switch(vid.renderpath)
6059 case RENDERPATH_GL11:
6060 case RENDERPATH_GL13:
6061 case RENDERPATH_GL20:
6062 case RENDERPATH_SOFT:
6063 case RENDERPATH_GLES1:
6064 case RENDERPATH_GLES2:
6066 case RENDERPATH_D3D9:
6067 case RENDERPATH_D3D10:
6068 case RENDERPATH_D3D11:
6071 for (i = 0;i < 4;i++)
6073 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6074 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6075 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6076 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6082 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6084 r_bloomstate.enabled = true;
6085 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6088 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);
6090 if (r_bloomstate.fbo_framebuffer)
6091 r_refdef.view.clear = true;
6094 void R_Bloom_CopyBloomTexture(float colorscale)
6096 r_refdef.stats.bloom++;
6098 // scale down screen texture to the bloom texture size
6100 R_Mesh_SetMainRenderTargets();
6101 R_SetViewport(&r_bloomstate.viewport);
6102 GL_BlendFunc(GL_ONE, GL_ZERO);
6103 GL_Color(colorscale, colorscale, colorscale, 1);
6104 // 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...
6105 switch(vid.renderpath)
6107 case RENDERPATH_GL11:
6108 case RENDERPATH_GL13:
6109 case RENDERPATH_GL20:
6110 case RENDERPATH_GLES1:
6111 case RENDERPATH_GLES2:
6112 case RENDERPATH_SOFT:
6113 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6115 case RENDERPATH_D3D9:
6116 case RENDERPATH_D3D10:
6117 case RENDERPATH_D3D11:
6118 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6121 // TODO: do boxfilter scale-down in shader?
6122 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6123 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6124 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6126 // we now have a bloom image in the framebuffer
6127 // copy it into the bloom image texture for later processing
6128 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);
6129 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6132 void R_Bloom_CopyHDRTexture(void)
6134 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);
6135 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6138 void R_Bloom_MakeTexture(void)
6141 float xoffset, yoffset, r, brighten;
6143 r_refdef.stats.bloom++;
6145 R_ResetViewRendering2D();
6147 // we have a bloom image in the framebuffer
6149 R_SetViewport(&r_bloomstate.viewport);
6151 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6154 r = bound(0, r_bloom_colorexponent.value / x, 1);
6155 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6157 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6158 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6159 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6160 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6162 // copy the vertically blurred bloom view to a texture
6163 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);
6164 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6167 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6168 brighten = r_bloom_brighten.value;
6169 if (r_bloomstate.hdr)
6170 brighten *= r_hdr_range.value;
6171 brighten = sqrt(brighten);
6173 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6174 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6176 for (dir = 0;dir < 2;dir++)
6178 // blend on at multiple vertical offsets to achieve a vertical blur
6179 // TODO: do offset blends using GLSL
6180 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6181 GL_BlendFunc(GL_ONE, GL_ZERO);
6182 for (x = -range;x <= range;x++)
6184 if (!dir){xoffset = 0;yoffset = x;}
6185 else {xoffset = x;yoffset = 0;}
6186 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6187 yoffset /= (float)r_bloomstate.bloomtextureheight;
6188 // compute a texcoord array with the specified x and y offset
6189 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6190 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6191 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6192 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6193 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6194 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6195 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6196 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6197 // this r value looks like a 'dot' particle, fading sharply to
6198 // black at the edges
6199 // (probably not realistic but looks good enough)
6200 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6201 //r = brighten/(range*2+1);
6202 r = brighten / (range * 2 + 1);
6204 r *= (1 - x*x/(float)(range*range));
6205 GL_Color(r, r, r, 1);
6206 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6207 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6208 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6209 GL_BlendFunc(GL_ONE, GL_ONE);
6212 // copy the vertically blurred bloom view to a texture
6213 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);
6214 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6218 void R_HDR_RenderBloomTexture(void)
6220 int oldwidth, oldheight;
6221 float oldcolorscale;
6222 qboolean oldwaterstate;
6224 oldwaterstate = r_waterstate.enabled;
6225 oldcolorscale = r_refdef.view.colorscale;
6226 oldwidth = r_refdef.view.width;
6227 oldheight = r_refdef.view.height;
6228 r_refdef.view.width = r_bloomstate.bloomwidth;
6229 r_refdef.view.height = r_bloomstate.bloomheight;
6231 if(r_hdr.integer < 2)
6232 r_waterstate.enabled = false;
6234 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6235 // TODO: add exposure compensation features
6236 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6238 r_refdef.view.showdebug = false;
6239 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6241 R_ResetViewRendering3D();
6243 R_ClearScreen(r_refdef.fogenabled);
6244 if (r_timereport_active)
6245 R_TimeReport("HDRclear");
6248 if (r_timereport_active)
6249 R_TimeReport("visibility");
6251 // only do secondary renders with HDR if r_hdr is 2 or higher
6252 r_waterstate.numwaterplanes = 0;
6253 if (r_waterstate.enabled)
6254 R_RenderWaterPlanes();
6256 r_refdef.view.showdebug = true;
6258 r_waterstate.numwaterplanes = 0;
6260 R_ResetViewRendering2D();
6262 R_Bloom_CopyHDRTexture();
6263 R_Bloom_MakeTexture();
6265 // restore the view settings
6266 r_waterstate.enabled = oldwaterstate;
6267 r_refdef.view.width = oldwidth;
6268 r_refdef.view.height = oldheight;
6269 r_refdef.view.colorscale = oldcolorscale;
6271 R_ResetViewRendering3D();
6273 R_ClearScreen(r_refdef.fogenabled);
6274 if (r_timereport_active)
6275 R_TimeReport("viewclear");
6278 static void R_BlendView(void)
6280 unsigned int permutation;
6281 float uservecs[4][4];
6283 switch (vid.renderpath)
6285 case RENDERPATH_GL20:
6286 case RENDERPATH_D3D9:
6287 case RENDERPATH_D3D10:
6288 case RENDERPATH_D3D11:
6289 case RENDERPATH_SOFT:
6290 case RENDERPATH_GLES2:
6292 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6293 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6294 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6295 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6296 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6298 if (r_bloomstate.texture_screen)
6300 // make sure the buffer is available
6301 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6303 R_ResetViewRendering2D();
6304 R_Mesh_SetMainRenderTargets();
6306 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6308 // declare variables
6309 float blur_factor, blur_mouseaccel, blur_velocity;
6310 static float blur_average;
6311 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6313 // set a goal for the factoring
6314 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6315 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6316 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6317 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6318 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6319 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6321 // from the goal, pick an averaged value between goal and last value
6322 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6323 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6325 // enforce minimum amount of blur
6326 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6328 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6330 // calculate values into a standard alpha
6331 cl.motionbluralpha = 1 - exp(-
6333 (r_motionblur.value * blur_factor / 80)
6335 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6338 max(0.0001, cl.time - cl.oldtime) // fps independent
6341 // randomization for the blur value to combat persistent ghosting
6342 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6343 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6346 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6348 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6349 GL_Color(1, 1, 1, cl.motionbluralpha);
6350 switch(vid.renderpath)
6352 case RENDERPATH_GL11:
6353 case RENDERPATH_GL13:
6354 case RENDERPATH_GL20:
6355 case RENDERPATH_GLES1:
6356 case RENDERPATH_GLES2:
6357 case RENDERPATH_SOFT:
6358 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6360 case RENDERPATH_D3D9:
6361 case RENDERPATH_D3D10:
6362 case RENDERPATH_D3D11:
6363 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6366 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6367 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6368 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6371 // updates old view angles for next pass
6372 VectorCopy(cl.viewangles, blur_oldangles);
6375 // copy view into the screen texture
6376 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);
6377 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6379 else if (!r_bloomstate.texture_bloom)
6381 // we may still have to do view tint...
6382 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6384 // apply a color tint to the whole view
6385 R_ResetViewRendering2D();
6386 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6387 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6388 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6389 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6390 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6392 break; // no screen processing, no bloom, skip it
6395 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6397 // render simple bloom effect
6398 // copy the screen and shrink it and darken it for the bloom process
6399 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6400 // make the bloom texture
6401 R_Bloom_MakeTexture();
6404 #if _MSC_VER >= 1400
6405 #define sscanf sscanf_s
6407 memset(uservecs, 0, sizeof(uservecs));
6408 if (r_glsl_postprocess_uservec1_enable.integer)
6409 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6410 if (r_glsl_postprocess_uservec2_enable.integer)
6411 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6412 if (r_glsl_postprocess_uservec3_enable.integer)
6413 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6414 if (r_glsl_postprocess_uservec4_enable.integer)
6415 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6417 R_ResetViewRendering2D();
6418 GL_Color(1, 1, 1, 1);
6419 GL_BlendFunc(GL_ONE, GL_ZERO);
6421 switch(vid.renderpath)
6423 case RENDERPATH_GL20:
6424 case RENDERPATH_GLES2:
6425 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6426 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6427 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6428 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6429 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6430 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]);
6431 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6432 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]);
6433 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]);
6434 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]);
6435 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]);
6436 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6437 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6438 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);
6440 case RENDERPATH_D3D9:
6442 // 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...
6443 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6444 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6445 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6446 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6447 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6448 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6449 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6450 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6451 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6452 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6453 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6454 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6455 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6456 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6459 case RENDERPATH_D3D10:
6460 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6462 case RENDERPATH_D3D11:
6463 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6465 case RENDERPATH_SOFT:
6466 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6467 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6468 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6469 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6470 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6471 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6472 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6473 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6474 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6475 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6476 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6477 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6478 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6479 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6484 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6485 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6487 case RENDERPATH_GL11:
6488 case RENDERPATH_GL13:
6489 case RENDERPATH_GLES1:
6490 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6492 // apply a color tint to the whole view
6493 R_ResetViewRendering2D();
6494 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6495 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6496 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6497 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6498 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6504 matrix4x4_t r_waterscrollmatrix;
6506 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6508 if (r_refdef.fog_density)
6510 r_refdef.fogcolor[0] = r_refdef.fog_red;
6511 r_refdef.fogcolor[1] = r_refdef.fog_green;
6512 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6514 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6515 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6516 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6517 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6521 VectorCopy(r_refdef.fogcolor, fogvec);
6522 // color.rgb *= ContrastBoost * SceneBrightness;
6523 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6524 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6525 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6526 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6531 void R_UpdateVariables(void)
6535 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6537 r_refdef.farclip = r_farclip_base.value;
6538 if (r_refdef.scene.worldmodel)
6539 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6540 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6542 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6543 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6544 r_refdef.polygonfactor = 0;
6545 r_refdef.polygonoffset = 0;
6546 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6547 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6549 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6550 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6551 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6552 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6553 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6554 if (FAKELIGHT_ENABLED)
6556 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6558 if (r_showsurfaces.integer)
6560 r_refdef.scene.rtworld = false;
6561 r_refdef.scene.rtworldshadows = false;
6562 r_refdef.scene.rtdlight = false;
6563 r_refdef.scene.rtdlightshadows = false;
6564 r_refdef.lightmapintensity = 0;
6567 if (gamemode == GAME_NEHAHRA)
6569 if (gl_fogenable.integer)
6571 r_refdef.oldgl_fogenable = true;
6572 r_refdef.fog_density = gl_fogdensity.value;
6573 r_refdef.fog_red = gl_fogred.value;
6574 r_refdef.fog_green = gl_foggreen.value;
6575 r_refdef.fog_blue = gl_fogblue.value;
6576 r_refdef.fog_alpha = 1;
6577 r_refdef.fog_start = 0;
6578 r_refdef.fog_end = gl_skyclip.value;
6579 r_refdef.fog_height = 1<<30;
6580 r_refdef.fog_fadedepth = 128;
6582 else if (r_refdef.oldgl_fogenable)
6584 r_refdef.oldgl_fogenable = false;
6585 r_refdef.fog_density = 0;
6586 r_refdef.fog_red = 0;
6587 r_refdef.fog_green = 0;
6588 r_refdef.fog_blue = 0;
6589 r_refdef.fog_alpha = 0;
6590 r_refdef.fog_start = 0;
6591 r_refdef.fog_end = 0;
6592 r_refdef.fog_height = 1<<30;
6593 r_refdef.fog_fadedepth = 128;
6597 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6598 r_refdef.fog_start = max(0, r_refdef.fog_start);
6599 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6601 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6603 if (r_refdef.fog_density && r_drawfog.integer)
6605 r_refdef.fogenabled = true;
6606 // this is the point where the fog reaches 0.9986 alpha, which we
6607 // consider a good enough cutoff point for the texture
6608 // (0.9986 * 256 == 255.6)
6609 if (r_fog_exp2.integer)
6610 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6612 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6613 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6614 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6615 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6616 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6617 R_BuildFogHeightTexture();
6618 // fog color was already set
6619 // update the fog texture
6620 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)
6621 R_BuildFogTexture();
6622 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6623 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6626 r_refdef.fogenabled = false;
6628 switch(vid.renderpath)
6630 case RENDERPATH_GL20:
6631 case RENDERPATH_D3D9:
6632 case RENDERPATH_D3D10:
6633 case RENDERPATH_D3D11:
6634 case RENDERPATH_SOFT:
6635 case RENDERPATH_GLES2:
6636 if(v_glslgamma.integer && !vid_gammatables_trivial)
6638 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6640 // build GLSL gamma texture
6641 #define RAMPWIDTH 256
6642 unsigned short ramp[RAMPWIDTH * 3];
6643 unsigned char rampbgr[RAMPWIDTH][4];
6646 r_texture_gammaramps_serial = vid_gammatables_serial;
6648 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6649 for(i = 0; i < RAMPWIDTH; ++i)
6651 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6652 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6653 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6656 if (r_texture_gammaramps)
6658 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6662 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6668 // remove GLSL gamma texture
6671 case RENDERPATH_GL11:
6672 case RENDERPATH_GL13:
6673 case RENDERPATH_GLES1:
6678 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6679 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6685 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6686 if( scenetype != r_currentscenetype ) {
6687 // store the old scenetype
6688 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6689 r_currentscenetype = scenetype;
6690 // move in the new scene
6691 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6700 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6702 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6703 if( scenetype == r_currentscenetype ) {
6704 return &r_refdef.scene;
6706 return &r_scenes_store[ scenetype ];
6715 int dpsoftrast_test;
6716 extern void R_Shadow_UpdateBounceGridTexture(void);
6717 extern cvar_t r_shadow_bouncegrid;
6718 void R_RenderView(void)
6720 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6722 dpsoftrast_test = r_test.integer;
6724 if (r_timereport_active)
6725 R_TimeReport("start");
6726 r_textureframe++; // used only by R_GetCurrentTexture
6727 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6729 if(R_CompileShader_CheckStaticParms())
6732 if (!r_drawentities.integer)
6733 r_refdef.scene.numentities = 0;
6735 R_AnimCache_ClearCache();
6736 R_FrameData_NewFrame();
6738 /* adjust for stereo display */
6739 if(R_Stereo_Active())
6741 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);
6742 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6745 if (r_refdef.view.isoverlay)
6747 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6748 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6749 R_TimeReport("depthclear");
6751 r_refdef.view.showdebug = false;
6753 r_waterstate.enabled = false;
6754 r_waterstate.numwaterplanes = 0;
6758 r_refdef.view.matrix = originalmatrix;
6764 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6766 r_refdef.view.matrix = originalmatrix;
6767 return; //Host_Error ("R_RenderView: NULL worldmodel");
6770 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6772 R_RenderView_UpdateViewVectors();
6774 R_Shadow_UpdateWorldLightSelection();
6776 R_Bloom_StartFrame();
6777 R_Water_StartFrame();
6780 if (r_timereport_active)
6781 R_TimeReport("viewsetup");
6783 R_ResetViewRendering3D();
6785 if (r_refdef.view.clear || r_refdef.fogenabled)
6787 R_ClearScreen(r_refdef.fogenabled);
6788 if (r_timereport_active)
6789 R_TimeReport("viewclear");
6791 r_refdef.view.clear = true;
6793 // this produces a bloom texture to be used in R_BlendView() later
6794 if (r_bloomstate.hdr)
6796 R_HDR_RenderBloomTexture();
6797 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6798 r_textureframe++; // used only by R_GetCurrentTexture
6801 r_refdef.view.showdebug = true;
6804 if (r_timereport_active)
6805 R_TimeReport("visibility");
6807 R_Shadow_UpdateBounceGridTexture();
6808 if (r_timereport_active && r_shadow_bouncegrid.integer)
6809 R_TimeReport("bouncegrid");
6811 r_waterstate.numwaterplanes = 0;
6812 if (r_waterstate.enabled)
6813 R_RenderWaterPlanes();
6816 r_waterstate.numwaterplanes = 0;
6819 if (r_timereport_active)
6820 R_TimeReport("blendview");
6822 GL_Scissor(0, 0, vid.width, vid.height);
6823 GL_ScissorTest(false);
6825 r_refdef.view.matrix = originalmatrix;
6830 void R_RenderWaterPlanes(void)
6832 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6834 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6835 if (r_timereport_active)
6836 R_TimeReport("waterworld");
6839 // don't let sound skip if going slow
6840 if (r_refdef.scene.extraupdate)
6843 R_DrawModelsAddWaterPlanes();
6844 if (r_timereport_active)
6845 R_TimeReport("watermodels");
6847 if (r_waterstate.numwaterplanes)
6849 R_Water_ProcessPlanes();
6850 if (r_timereport_active)
6851 R_TimeReport("waterscenes");
6855 extern void R_DrawLightningBeams (void);
6856 extern void VM_CL_AddPolygonsToMeshQueue (void);
6857 extern void R_DrawPortals (void);
6858 extern cvar_t cl_locs_show;
6859 static void R_DrawLocs(void);
6860 static void R_DrawEntityBBoxes(void);
6861 static void R_DrawModelDecals(void);
6862 extern void R_DrawModelShadows(void);
6863 extern void R_DrawModelShadowMaps(void);
6864 extern cvar_t cl_decals_newsystem;
6865 extern qboolean r_shadow_usingdeferredprepass;
6866 void R_RenderScene(void)
6868 qboolean shadowmapping = false;
6870 if (r_timereport_active)
6871 R_TimeReport("beginscene");
6873 r_refdef.stats.renders++;
6877 // don't let sound skip if going slow
6878 if (r_refdef.scene.extraupdate)
6881 R_MeshQueue_BeginScene();
6885 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);
6887 if (r_timereport_active)
6888 R_TimeReport("skystartframe");
6890 if (cl.csqc_vidvars.drawworld)
6892 // don't let sound skip if going slow
6893 if (r_refdef.scene.extraupdate)
6896 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6898 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6899 if (r_timereport_active)
6900 R_TimeReport("worldsky");
6903 if (R_DrawBrushModelsSky() && r_timereport_active)
6904 R_TimeReport("bmodelsky");
6906 if (skyrendermasked && skyrenderlater)
6908 // we have to force off the water clipping plane while rendering sky
6912 if (r_timereport_active)
6913 R_TimeReport("sky");
6917 R_AnimCache_CacheVisibleEntities();
6918 if (r_timereport_active)
6919 R_TimeReport("animation");
6921 R_Shadow_PrepareLights();
6922 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6923 R_Shadow_PrepareModelShadows();
6924 if (r_timereport_active)
6925 R_TimeReport("preparelights");
6927 if (R_Shadow_ShadowMappingEnabled())
6928 shadowmapping = true;
6930 if (r_shadow_usingdeferredprepass)
6931 R_Shadow_DrawPrepass();
6933 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6935 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6936 if (r_timereport_active)
6937 R_TimeReport("worlddepth");
6939 if (r_depthfirst.integer >= 2)
6941 R_DrawModelsDepth();
6942 if (r_timereport_active)
6943 R_TimeReport("modeldepth");
6946 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6948 R_DrawModelShadowMaps();
6949 R_ResetViewRendering3D();
6950 // don't let sound skip if going slow
6951 if (r_refdef.scene.extraupdate)
6955 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6957 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6958 if (r_timereport_active)
6959 R_TimeReport("world");
6962 // don't let sound skip if going slow
6963 if (r_refdef.scene.extraupdate)
6967 if (r_timereport_active)
6968 R_TimeReport("models");
6970 // don't let sound skip if going slow
6971 if (r_refdef.scene.extraupdate)
6974 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6976 R_DrawModelShadows();
6977 R_ResetViewRendering3D();
6978 // don't let sound skip if going slow
6979 if (r_refdef.scene.extraupdate)
6983 if (!r_shadow_usingdeferredprepass)
6985 R_Shadow_DrawLights();
6986 if (r_timereport_active)
6987 R_TimeReport("rtlights");
6990 // don't let sound skip if going slow
6991 if (r_refdef.scene.extraupdate)
6994 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6996 R_DrawModelShadows();
6997 R_ResetViewRendering3D();
6998 // don't let sound skip if going slow
6999 if (r_refdef.scene.extraupdate)
7003 if (cl.csqc_vidvars.drawworld)
7005 if (cl_decals_newsystem.integer)
7007 R_DrawModelDecals();
7008 if (r_timereport_active)
7009 R_TimeReport("modeldecals");
7014 if (r_timereport_active)
7015 R_TimeReport("decals");
7019 if (r_timereport_active)
7020 R_TimeReport("particles");
7023 if (r_timereport_active)
7024 R_TimeReport("explosions");
7026 R_DrawLightningBeams();
7027 if (r_timereport_active)
7028 R_TimeReport("lightning");
7031 VM_CL_AddPolygonsToMeshQueue();
7033 if (r_refdef.view.showdebug)
7035 if (cl_locs_show.integer)
7038 if (r_timereport_active)
7039 R_TimeReport("showlocs");
7042 if (r_drawportals.integer)
7045 if (r_timereport_active)
7046 R_TimeReport("portals");
7049 if (r_showbboxes.value > 0)
7051 R_DrawEntityBBoxes();
7052 if (r_timereport_active)
7053 R_TimeReport("bboxes");
7057 if (r_transparent.integer)
7059 R_MeshQueue_RenderTransparent();
7060 if (r_timereport_active)
7061 R_TimeReport("drawtrans");
7064 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))
7066 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7067 if (r_timereport_active)
7068 R_TimeReport("worlddebug");
7069 R_DrawModelsDebug();
7070 if (r_timereport_active)
7071 R_TimeReport("modeldebug");
7074 if (cl.csqc_vidvars.drawworld)
7076 R_Shadow_DrawCoronas();
7077 if (r_timereport_active)
7078 R_TimeReport("coronas");
7083 GL_DepthTest(false);
7084 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7085 GL_Color(1, 1, 1, 1);
7086 qglBegin(GL_POLYGON);
7087 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7088 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7089 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7090 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7092 qglBegin(GL_POLYGON);
7093 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]);
7094 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]);
7095 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]);
7096 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]);
7098 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7102 // don't let sound skip if going slow
7103 if (r_refdef.scene.extraupdate)
7106 R_ResetViewRendering2D();
7109 static const unsigned short bboxelements[36] =
7119 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7122 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7124 RSurf_ActiveWorldEntity();
7126 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7127 GL_DepthMask(false);
7128 GL_DepthRange(0, 1);
7129 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7130 // R_Mesh_ResetTextureState();
7132 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7133 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7134 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7135 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7136 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7137 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7138 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7139 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7140 R_FillColors(color4f, 8, cr, cg, cb, ca);
7141 if (r_refdef.fogenabled)
7143 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7145 f1 = RSurf_FogVertex(v);
7147 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7148 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7149 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7152 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7153 R_Mesh_ResetTextureState();
7154 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7155 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7158 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7162 prvm_edict_t *edict;
7163 prvm_prog_t *prog_save = prog;
7165 // this function draws bounding boxes of server entities
7169 GL_CullFace(GL_NONE);
7170 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7174 for (i = 0;i < numsurfaces;i++)
7176 edict = PRVM_EDICT_NUM(surfacelist[i]);
7177 switch ((int)PRVM_serveredictfloat(edict, solid))
7179 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7180 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7181 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7182 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7183 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7184 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7186 color[3] *= r_showbboxes.value;
7187 color[3] = bound(0, color[3], 1);
7188 GL_DepthTest(!r_showdisabledepthtest.integer);
7189 GL_CullFace(r_refdef.view.cullface_front);
7190 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7196 static void R_DrawEntityBBoxes(void)
7199 prvm_edict_t *edict;
7201 prvm_prog_t *prog_save = prog;
7203 // this function draws bounding boxes of server entities
7209 for (i = 0;i < prog->num_edicts;i++)
7211 edict = PRVM_EDICT_NUM(i);
7212 if (edict->priv.server->free)
7214 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7215 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7217 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7219 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7220 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7226 static const int nomodelelement3i[24] =
7238 static const unsigned short nomodelelement3s[24] =
7250 static const float nomodelvertex3f[6*3] =
7260 static const float nomodelcolor4f[6*4] =
7262 0.0f, 0.0f, 0.5f, 1.0f,
7263 0.0f, 0.0f, 0.5f, 1.0f,
7264 0.0f, 0.5f, 0.0f, 1.0f,
7265 0.0f, 0.5f, 0.0f, 1.0f,
7266 0.5f, 0.0f, 0.0f, 1.0f,
7267 0.5f, 0.0f, 0.0f, 1.0f
7270 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7276 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);
7278 // this is only called once per entity so numsurfaces is always 1, and
7279 // surfacelist is always {0}, so this code does not handle batches
7281 if (rsurface.ent_flags & RENDER_ADDITIVE)
7283 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7284 GL_DepthMask(false);
7286 else if (rsurface.colormod[3] < 1)
7288 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7289 GL_DepthMask(false);
7293 GL_BlendFunc(GL_ONE, GL_ZERO);
7296 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7297 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7298 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7299 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7300 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7301 for (i = 0, c = color4f;i < 6;i++, c += 4)
7303 c[0] *= rsurface.colormod[0];
7304 c[1] *= rsurface.colormod[1];
7305 c[2] *= rsurface.colormod[2];
7306 c[3] *= rsurface.colormod[3];
7308 if (r_refdef.fogenabled)
7310 for (i = 0, c = color4f;i < 6;i++, c += 4)
7312 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7314 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7315 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7316 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7319 // R_Mesh_ResetTextureState();
7320 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7321 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7322 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7325 void R_DrawNoModel(entity_render_t *ent)
7328 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7329 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7330 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7332 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7335 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7337 vec3_t right1, right2, diff, normal;
7339 VectorSubtract (org2, org1, normal);
7341 // calculate 'right' vector for start
7342 VectorSubtract (r_refdef.view.origin, org1, diff);
7343 CrossProduct (normal, diff, right1);
7344 VectorNormalize (right1);
7346 // calculate 'right' vector for end
7347 VectorSubtract (r_refdef.view.origin, org2, diff);
7348 CrossProduct (normal, diff, right2);
7349 VectorNormalize (right2);
7351 vert[ 0] = org1[0] + width * right1[0];
7352 vert[ 1] = org1[1] + width * right1[1];
7353 vert[ 2] = org1[2] + width * right1[2];
7354 vert[ 3] = org1[0] - width * right1[0];
7355 vert[ 4] = org1[1] - width * right1[1];
7356 vert[ 5] = org1[2] - width * right1[2];
7357 vert[ 6] = org2[0] - width * right2[0];
7358 vert[ 7] = org2[1] - width * right2[1];
7359 vert[ 8] = org2[2] - width * right2[2];
7360 vert[ 9] = org2[0] + width * right2[0];
7361 vert[10] = org2[1] + width * right2[1];
7362 vert[11] = org2[2] + width * right2[2];
7365 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)
7367 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7368 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7369 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7370 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7371 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7372 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7373 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7374 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7375 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7376 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7377 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7378 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7381 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7386 VectorSet(v, x, y, z);
7387 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7388 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7390 if (i == mesh->numvertices)
7392 if (mesh->numvertices < mesh->maxvertices)
7394 VectorCopy(v, vertex3f);
7395 mesh->numvertices++;
7397 return mesh->numvertices;
7403 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7407 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7408 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7409 e = mesh->element3i + mesh->numtriangles * 3;
7410 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7412 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7413 if (mesh->numtriangles < mesh->maxtriangles)
7418 mesh->numtriangles++;
7420 element[1] = element[2];
7424 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7428 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7429 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7430 e = mesh->element3i + mesh->numtriangles * 3;
7431 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7433 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7434 if (mesh->numtriangles < mesh->maxtriangles)
7439 mesh->numtriangles++;
7441 element[1] = element[2];
7445 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7446 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7448 int planenum, planenum2;
7451 mplane_t *plane, *plane2;
7453 double temppoints[2][256*3];
7454 // figure out how large a bounding box we need to properly compute this brush
7456 for (w = 0;w < numplanes;w++)
7457 maxdist = max(maxdist, fabs(planes[w].dist));
7458 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7459 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7460 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7464 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7465 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7467 if (planenum2 == planenum)
7469 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);
7472 if (tempnumpoints < 3)
7474 // generate elements forming a triangle fan for this polygon
7475 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7479 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)
7481 texturelayer_t *layer;
7482 layer = t->currentlayers + t->currentnumlayers++;
7484 layer->depthmask = depthmask;
7485 layer->blendfunc1 = blendfunc1;
7486 layer->blendfunc2 = blendfunc2;
7487 layer->texture = texture;
7488 layer->texmatrix = *matrix;
7489 layer->color[0] = r;
7490 layer->color[1] = g;
7491 layer->color[2] = b;
7492 layer->color[3] = a;
7495 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7497 if(parms[0] == 0 && parms[1] == 0)
7499 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7500 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7505 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7508 index = parms[2] + rsurface.shadertime * parms[3];
7509 index -= floor(index);
7510 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7513 case Q3WAVEFUNC_NONE:
7514 case Q3WAVEFUNC_NOISE:
7515 case Q3WAVEFUNC_COUNT:
7518 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7519 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7520 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7521 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7522 case Q3WAVEFUNC_TRIANGLE:
7524 f = index - floor(index);
7537 f = parms[0] + parms[1] * f;
7538 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7539 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7543 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7549 matrix4x4_t matrix, temp;
7550 switch(tcmod->tcmod)
7554 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7555 matrix = r_waterscrollmatrix;
7557 matrix = identitymatrix;
7559 case Q3TCMOD_ENTITYTRANSLATE:
7560 // this is used in Q3 to allow the gamecode to control texcoord
7561 // scrolling on the entity, which is not supported in darkplaces yet.
7562 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7564 case Q3TCMOD_ROTATE:
7565 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7566 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7567 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7570 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7572 case Q3TCMOD_SCROLL:
7573 // extra care is needed because of precision breakdown with large values of time
7574 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7575 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7576 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7578 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7579 w = (int) tcmod->parms[0];
7580 h = (int) tcmod->parms[1];
7581 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7583 idx = (int) floor(f * w * h);
7584 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7586 case Q3TCMOD_STRETCH:
7587 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7588 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7590 case Q3TCMOD_TRANSFORM:
7591 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7592 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7593 VectorSet(tcmat + 6, 0 , 0 , 1);
7594 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7595 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7597 case Q3TCMOD_TURBULENT:
7598 // this is handled in the RSurf_PrepareVertices function
7599 matrix = identitymatrix;
7603 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7606 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7608 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7609 char name[MAX_QPATH];
7610 skinframe_t *skinframe;
7611 unsigned char pixels[296*194];
7612 strlcpy(cache->name, skinname, sizeof(cache->name));
7613 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7614 if (developer_loading.integer)
7615 Con_Printf("loading %s\n", name);
7616 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7617 if (!skinframe || !skinframe->base)
7620 fs_offset_t filesize;
7622 f = FS_LoadFile(name, tempmempool, true, &filesize);
7625 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7626 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7630 cache->skinframe = skinframe;
7633 texture_t *R_GetCurrentTexture(texture_t *t)
7636 const entity_render_t *ent = rsurface.entity;
7637 dp_model_t *model = ent->model;
7638 q3shaderinfo_layer_tcmod_t *tcmod;
7640 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7641 return t->currentframe;
7642 t->update_lastrenderframe = r_textureframe;
7643 t->update_lastrenderentity = (void *)ent;
7645 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7646 t->camera_entity = ent->entitynumber;
7648 t->camera_entity = 0;
7650 // switch to an alternate material if this is a q1bsp animated material
7652 texture_t *texture = t;
7653 int s = rsurface.ent_skinnum;
7654 if ((unsigned int)s >= (unsigned int)model->numskins)
7656 if (model->skinscenes)
7658 if (model->skinscenes[s].framecount > 1)
7659 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7661 s = model->skinscenes[s].firstframe;
7664 t = t + s * model->num_surfaces;
7667 // use an alternate animation if the entity's frame is not 0,
7668 // and only if the texture has an alternate animation
7669 if (rsurface.ent_alttextures && t->anim_total[1])
7670 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7672 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7674 texture->currentframe = t;
7677 // update currentskinframe to be a qw skin or animation frame
7678 if (rsurface.ent_qwskin >= 0)
7680 i = rsurface.ent_qwskin;
7681 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7683 r_qwskincache_size = cl.maxclients;
7685 Mem_Free(r_qwskincache);
7686 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7688 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7689 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7690 t->currentskinframe = r_qwskincache[i].skinframe;
7691 if (t->currentskinframe == NULL)
7692 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7694 else if (t->numskinframes >= 2)
7695 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7696 if (t->backgroundnumskinframes >= 2)
7697 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7699 t->currentmaterialflags = t->basematerialflags;
7700 t->currentalpha = rsurface.colormod[3];
7701 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7702 t->currentalpha *= r_wateralpha.value;
7703 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7704 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7705 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7706 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7707 if (!(rsurface.ent_flags & RENDER_LIGHT))
7708 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7709 else if (FAKELIGHT_ENABLED)
7711 // no modellight if using fakelight for the map
7713 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7715 // pick a model lighting mode
7716 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7717 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7719 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7721 if (rsurface.ent_flags & RENDER_ADDITIVE)
7722 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7723 else if (t->currentalpha < 1)
7724 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7725 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7726 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7727 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7728 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7729 if (t->backgroundnumskinframes)
7730 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7731 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7733 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7734 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7737 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7738 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7740 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7741 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7743 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7744 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7746 // there is no tcmod
7747 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7749 t->currenttexmatrix = r_waterscrollmatrix;
7750 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7752 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7754 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7755 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7758 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7759 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7760 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7761 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7763 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7764 if (t->currentskinframe->qpixels)
7765 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7766 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7767 if (!t->basetexture)
7768 t->basetexture = r_texture_notexture;
7769 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7770 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7771 t->nmaptexture = t->currentskinframe->nmap;
7772 if (!t->nmaptexture)
7773 t->nmaptexture = r_texture_blanknormalmap;
7774 t->glosstexture = r_texture_black;
7775 t->glowtexture = t->currentskinframe->glow;
7776 t->fogtexture = t->currentskinframe->fog;
7777 t->reflectmasktexture = t->currentskinframe->reflect;
7778 if (t->backgroundnumskinframes)
7780 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7781 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7782 t->backgroundglosstexture = r_texture_black;
7783 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7784 if (!t->backgroundnmaptexture)
7785 t->backgroundnmaptexture = r_texture_blanknormalmap;
7789 t->backgroundbasetexture = r_texture_white;
7790 t->backgroundnmaptexture = r_texture_blanknormalmap;
7791 t->backgroundglosstexture = r_texture_black;
7792 t->backgroundglowtexture = NULL;
7794 t->specularpower = r_shadow_glossexponent.value;
7795 // TODO: store reference values for these in the texture?
7796 t->specularscale = 0;
7797 if (r_shadow_gloss.integer > 0)
7799 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7801 if (r_shadow_glossintensity.value > 0)
7803 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7804 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7805 t->specularscale = r_shadow_glossintensity.value;
7808 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7810 t->glosstexture = r_texture_white;
7811 t->backgroundglosstexture = r_texture_white;
7812 t->specularscale = r_shadow_gloss2intensity.value;
7813 t->specularpower = r_shadow_gloss2exponent.value;
7816 t->specularscale *= t->specularscalemod;
7817 t->specularpower *= t->specularpowermod;
7819 // lightmaps mode looks bad with dlights using actual texturing, so turn
7820 // off the colormap and glossmap, but leave the normalmap on as it still
7821 // accurately represents the shading involved
7822 if (gl_lightmaps.integer)
7824 t->basetexture = r_texture_grey128;
7825 t->pantstexture = r_texture_black;
7826 t->shirttexture = r_texture_black;
7827 t->nmaptexture = r_texture_blanknormalmap;
7828 t->glosstexture = r_texture_black;
7829 t->glowtexture = NULL;
7830 t->fogtexture = NULL;
7831 t->reflectmasktexture = NULL;
7832 t->backgroundbasetexture = NULL;
7833 t->backgroundnmaptexture = r_texture_blanknormalmap;
7834 t->backgroundglosstexture = r_texture_black;
7835 t->backgroundglowtexture = NULL;
7836 t->specularscale = 0;
7837 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7840 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7841 VectorClear(t->dlightcolor);
7842 t->currentnumlayers = 0;
7843 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7845 int blendfunc1, blendfunc2;
7847 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7849 blendfunc1 = GL_SRC_ALPHA;
7850 blendfunc2 = GL_ONE;
7852 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7854 blendfunc1 = GL_SRC_ALPHA;
7855 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7857 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7859 blendfunc1 = t->customblendfunc[0];
7860 blendfunc2 = t->customblendfunc[1];
7864 blendfunc1 = GL_ONE;
7865 blendfunc2 = GL_ZERO;
7867 // don't colormod evilblend textures
7868 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7869 VectorSet(t->lightmapcolor, 1, 1, 1);
7870 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7871 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7873 // fullbright is not affected by r_refdef.lightmapintensity
7874 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]);
7875 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7876 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]);
7877 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7878 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]);
7882 vec3_t ambientcolor;
7884 // set the color tint used for lights affecting this surface
7885 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7887 // q3bsp has no lightmap updates, so the lightstylevalue that
7888 // would normally be baked into the lightmap must be
7889 // applied to the color
7890 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7891 if (model->type == mod_brushq3)
7892 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7893 colorscale *= r_refdef.lightmapintensity;
7894 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7895 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7896 // basic lit geometry
7897 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]);
7898 // add pants/shirt if needed
7899 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7900 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]);
7901 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7902 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]);
7903 // now add ambient passes if needed
7904 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7906 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]);
7907 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7908 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]);
7909 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7910 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]);
7913 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7914 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]);
7915 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7917 // if this is opaque use alpha blend which will darken the earlier
7920 // if this is an alpha blended material, all the earlier passes
7921 // were darkened by fog already, so we only need to add the fog
7922 // color ontop through the fog mask texture
7924 // if this is an additive blended material, all the earlier passes
7925 // were darkened by fog already, and we should not add fog color
7926 // (because the background was not darkened, there is no fog color
7927 // that was lost behind it).
7928 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]);
7932 return t->currentframe;
7935 rsurfacestate_t rsurface;
7937 void RSurf_ActiveWorldEntity(void)
7939 dp_model_t *model = r_refdef.scene.worldmodel;
7940 //if (rsurface.entity == r_refdef.scene.worldentity)
7942 rsurface.entity = r_refdef.scene.worldentity;
7943 rsurface.skeleton = NULL;
7944 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7945 rsurface.ent_skinnum = 0;
7946 rsurface.ent_qwskin = -1;
7947 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7948 rsurface.shadertime = r_refdef.scene.time;
7949 rsurface.matrix = identitymatrix;
7950 rsurface.inversematrix = identitymatrix;
7951 rsurface.matrixscale = 1;
7952 rsurface.inversematrixscale = 1;
7953 R_EntityMatrix(&identitymatrix);
7954 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7955 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7956 rsurface.fograngerecip = r_refdef.fograngerecip;
7957 rsurface.fogheightfade = r_refdef.fogheightfade;
7958 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7959 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7960 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7961 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7962 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7963 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7964 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7965 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7966 rsurface.colormod[3] = 1;
7967 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);
7968 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7969 rsurface.frameblend[0].lerp = 1;
7970 rsurface.ent_alttextures = false;
7971 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7972 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7973 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7974 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7975 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7976 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7977 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7978 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7979 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7980 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7981 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7982 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7983 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7984 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7985 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7986 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7987 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7988 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7989 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7990 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7991 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7992 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7993 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7994 rsurface.modelelement3i = model->surfmesh.data_element3i;
7995 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7996 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7997 rsurface.modelelement3s = model->surfmesh.data_element3s;
7998 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7999 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8000 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8001 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8002 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8003 rsurface.modelsurfaces = model->data_surfaces;
8004 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8005 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8006 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8007 rsurface.modelgeneratedvertex = false;
8008 rsurface.batchgeneratedvertex = false;
8009 rsurface.batchfirstvertex = 0;
8010 rsurface.batchnumvertices = 0;
8011 rsurface.batchfirsttriangle = 0;
8012 rsurface.batchnumtriangles = 0;
8013 rsurface.batchvertex3f = NULL;
8014 rsurface.batchvertex3f_vertexbuffer = NULL;
8015 rsurface.batchvertex3f_bufferoffset = 0;
8016 rsurface.batchsvector3f = NULL;
8017 rsurface.batchsvector3f_vertexbuffer = NULL;
8018 rsurface.batchsvector3f_bufferoffset = 0;
8019 rsurface.batchtvector3f = NULL;
8020 rsurface.batchtvector3f_vertexbuffer = NULL;
8021 rsurface.batchtvector3f_bufferoffset = 0;
8022 rsurface.batchnormal3f = NULL;
8023 rsurface.batchnormal3f_vertexbuffer = NULL;
8024 rsurface.batchnormal3f_bufferoffset = 0;
8025 rsurface.batchlightmapcolor4f = NULL;
8026 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8027 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8028 rsurface.batchtexcoordtexture2f = NULL;
8029 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8030 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8031 rsurface.batchtexcoordlightmap2f = NULL;
8032 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8033 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8034 rsurface.batchvertexmesh = NULL;
8035 rsurface.batchvertexmeshbuffer = NULL;
8036 rsurface.batchvertex3fbuffer = NULL;
8037 rsurface.batchelement3i = NULL;
8038 rsurface.batchelement3i_indexbuffer = NULL;
8039 rsurface.batchelement3i_bufferoffset = 0;
8040 rsurface.batchelement3s = NULL;
8041 rsurface.batchelement3s_indexbuffer = NULL;
8042 rsurface.batchelement3s_bufferoffset = 0;
8043 rsurface.passcolor4f = NULL;
8044 rsurface.passcolor4f_vertexbuffer = NULL;
8045 rsurface.passcolor4f_bufferoffset = 0;
8048 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8050 dp_model_t *model = ent->model;
8051 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8053 rsurface.entity = (entity_render_t *)ent;
8054 rsurface.skeleton = ent->skeleton;
8055 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8056 rsurface.ent_skinnum = ent->skinnum;
8057 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;
8058 rsurface.ent_flags = ent->flags;
8059 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8060 rsurface.matrix = ent->matrix;
8061 rsurface.inversematrix = ent->inversematrix;
8062 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8063 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8064 R_EntityMatrix(&rsurface.matrix);
8065 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8066 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8067 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8068 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8069 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8070 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8071 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8072 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8073 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8074 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8075 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8076 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8077 rsurface.colormod[3] = ent->alpha;
8078 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8079 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8080 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8081 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8082 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8083 if (ent->model->brush.submodel && !prepass)
8085 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8086 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8088 if (model->surfmesh.isanimated && model->AnimateVertices)
8090 if (ent->animcache_vertex3f)
8092 rsurface.modelvertex3f = ent->animcache_vertex3f;
8093 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8094 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8095 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8096 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8097 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8098 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8100 else if (wanttangents)
8102 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8103 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8104 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8105 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8106 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8107 rsurface.modelvertexmesh = NULL;
8108 rsurface.modelvertexmeshbuffer = NULL;
8109 rsurface.modelvertex3fbuffer = NULL;
8111 else if (wantnormals)
8113 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8114 rsurface.modelsvector3f = NULL;
8115 rsurface.modeltvector3f = NULL;
8116 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8117 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8118 rsurface.modelvertexmesh = NULL;
8119 rsurface.modelvertexmeshbuffer = NULL;
8120 rsurface.modelvertex3fbuffer = NULL;
8124 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8125 rsurface.modelsvector3f = NULL;
8126 rsurface.modeltvector3f = NULL;
8127 rsurface.modelnormal3f = NULL;
8128 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8129 rsurface.modelvertexmesh = NULL;
8130 rsurface.modelvertexmeshbuffer = NULL;
8131 rsurface.modelvertex3fbuffer = NULL;
8133 rsurface.modelvertex3f_vertexbuffer = 0;
8134 rsurface.modelvertex3f_bufferoffset = 0;
8135 rsurface.modelsvector3f_vertexbuffer = 0;
8136 rsurface.modelsvector3f_bufferoffset = 0;
8137 rsurface.modeltvector3f_vertexbuffer = 0;
8138 rsurface.modeltvector3f_bufferoffset = 0;
8139 rsurface.modelnormal3f_vertexbuffer = 0;
8140 rsurface.modelnormal3f_bufferoffset = 0;
8141 rsurface.modelgeneratedvertex = true;
8145 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8146 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8147 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8148 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8149 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8150 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8151 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8152 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8153 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8154 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8155 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8156 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8157 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8158 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8159 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8160 rsurface.modelgeneratedvertex = false;
8162 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8163 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8164 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8165 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8166 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8167 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8168 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8169 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8170 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8171 rsurface.modelelement3i = model->surfmesh.data_element3i;
8172 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8173 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8174 rsurface.modelelement3s = model->surfmesh.data_element3s;
8175 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8176 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8177 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8178 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8179 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8180 rsurface.modelsurfaces = model->data_surfaces;
8181 rsurface.batchgeneratedvertex = false;
8182 rsurface.batchfirstvertex = 0;
8183 rsurface.batchnumvertices = 0;
8184 rsurface.batchfirsttriangle = 0;
8185 rsurface.batchnumtriangles = 0;
8186 rsurface.batchvertex3f = NULL;
8187 rsurface.batchvertex3f_vertexbuffer = NULL;
8188 rsurface.batchvertex3f_bufferoffset = 0;
8189 rsurface.batchsvector3f = NULL;
8190 rsurface.batchsvector3f_vertexbuffer = NULL;
8191 rsurface.batchsvector3f_bufferoffset = 0;
8192 rsurface.batchtvector3f = NULL;
8193 rsurface.batchtvector3f_vertexbuffer = NULL;
8194 rsurface.batchtvector3f_bufferoffset = 0;
8195 rsurface.batchnormal3f = NULL;
8196 rsurface.batchnormal3f_vertexbuffer = NULL;
8197 rsurface.batchnormal3f_bufferoffset = 0;
8198 rsurface.batchlightmapcolor4f = NULL;
8199 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8200 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8201 rsurface.batchtexcoordtexture2f = NULL;
8202 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8203 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8204 rsurface.batchtexcoordlightmap2f = NULL;
8205 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8206 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8207 rsurface.batchvertexmesh = NULL;
8208 rsurface.batchvertexmeshbuffer = NULL;
8209 rsurface.batchvertex3fbuffer = NULL;
8210 rsurface.batchelement3i = NULL;
8211 rsurface.batchelement3i_indexbuffer = NULL;
8212 rsurface.batchelement3i_bufferoffset = 0;
8213 rsurface.batchelement3s = NULL;
8214 rsurface.batchelement3s_indexbuffer = NULL;
8215 rsurface.batchelement3s_bufferoffset = 0;
8216 rsurface.passcolor4f = NULL;
8217 rsurface.passcolor4f_vertexbuffer = NULL;
8218 rsurface.passcolor4f_bufferoffset = 0;
8221 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)
8223 rsurface.entity = r_refdef.scene.worldentity;
8224 rsurface.skeleton = NULL;
8225 rsurface.ent_skinnum = 0;
8226 rsurface.ent_qwskin = -1;
8227 rsurface.ent_flags = entflags;
8228 rsurface.shadertime = r_refdef.scene.time - shadertime;
8229 rsurface.modelnumvertices = numvertices;
8230 rsurface.modelnumtriangles = numtriangles;
8231 rsurface.matrix = *matrix;
8232 rsurface.inversematrix = *inversematrix;
8233 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8234 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8235 R_EntityMatrix(&rsurface.matrix);
8236 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8237 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8238 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8239 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8240 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8241 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8242 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8243 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8244 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8245 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8246 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8247 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8248 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);
8249 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8250 rsurface.frameblend[0].lerp = 1;
8251 rsurface.ent_alttextures = false;
8252 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8253 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8256 rsurface.modelvertex3f = (float *)vertex3f;
8257 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8258 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8259 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8261 else if (wantnormals)
8263 rsurface.modelvertex3f = (float *)vertex3f;
8264 rsurface.modelsvector3f = NULL;
8265 rsurface.modeltvector3f = NULL;
8266 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8270 rsurface.modelvertex3f = (float *)vertex3f;
8271 rsurface.modelsvector3f = NULL;
8272 rsurface.modeltvector3f = NULL;
8273 rsurface.modelnormal3f = NULL;
8275 rsurface.modelvertexmesh = NULL;
8276 rsurface.modelvertexmeshbuffer = NULL;
8277 rsurface.modelvertex3fbuffer = NULL;
8278 rsurface.modelvertex3f_vertexbuffer = 0;
8279 rsurface.modelvertex3f_bufferoffset = 0;
8280 rsurface.modelsvector3f_vertexbuffer = 0;
8281 rsurface.modelsvector3f_bufferoffset = 0;
8282 rsurface.modeltvector3f_vertexbuffer = 0;
8283 rsurface.modeltvector3f_bufferoffset = 0;
8284 rsurface.modelnormal3f_vertexbuffer = 0;
8285 rsurface.modelnormal3f_bufferoffset = 0;
8286 rsurface.modelgeneratedvertex = true;
8287 rsurface.modellightmapcolor4f = (float *)color4f;
8288 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8289 rsurface.modellightmapcolor4f_bufferoffset = 0;
8290 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8291 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8292 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8293 rsurface.modeltexcoordlightmap2f = NULL;
8294 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8295 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8296 rsurface.modelelement3i = (int *)element3i;
8297 rsurface.modelelement3i_indexbuffer = NULL;
8298 rsurface.modelelement3i_bufferoffset = 0;
8299 rsurface.modelelement3s = (unsigned short *)element3s;
8300 rsurface.modelelement3s_indexbuffer = NULL;
8301 rsurface.modelelement3s_bufferoffset = 0;
8302 rsurface.modellightmapoffsets = NULL;
8303 rsurface.modelsurfaces = NULL;
8304 rsurface.batchgeneratedvertex = false;
8305 rsurface.batchfirstvertex = 0;
8306 rsurface.batchnumvertices = 0;
8307 rsurface.batchfirsttriangle = 0;
8308 rsurface.batchnumtriangles = 0;
8309 rsurface.batchvertex3f = NULL;
8310 rsurface.batchvertex3f_vertexbuffer = NULL;
8311 rsurface.batchvertex3f_bufferoffset = 0;
8312 rsurface.batchsvector3f = NULL;
8313 rsurface.batchsvector3f_vertexbuffer = NULL;
8314 rsurface.batchsvector3f_bufferoffset = 0;
8315 rsurface.batchtvector3f = NULL;
8316 rsurface.batchtvector3f_vertexbuffer = NULL;
8317 rsurface.batchtvector3f_bufferoffset = 0;
8318 rsurface.batchnormal3f = NULL;
8319 rsurface.batchnormal3f_vertexbuffer = NULL;
8320 rsurface.batchnormal3f_bufferoffset = 0;
8321 rsurface.batchlightmapcolor4f = NULL;
8322 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8323 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8324 rsurface.batchtexcoordtexture2f = NULL;
8325 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8326 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8327 rsurface.batchtexcoordlightmap2f = NULL;
8328 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8329 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8330 rsurface.batchvertexmesh = NULL;
8331 rsurface.batchvertexmeshbuffer = NULL;
8332 rsurface.batchvertex3fbuffer = NULL;
8333 rsurface.batchelement3i = NULL;
8334 rsurface.batchelement3i_indexbuffer = NULL;
8335 rsurface.batchelement3i_bufferoffset = 0;
8336 rsurface.batchelement3s = NULL;
8337 rsurface.batchelement3s_indexbuffer = NULL;
8338 rsurface.batchelement3s_bufferoffset = 0;
8339 rsurface.passcolor4f = NULL;
8340 rsurface.passcolor4f_vertexbuffer = NULL;
8341 rsurface.passcolor4f_bufferoffset = 0;
8343 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8345 if ((wantnormals || wanttangents) && !normal3f)
8347 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8348 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8350 if (wanttangents && !svector3f)
8352 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8353 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8354 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8359 float RSurf_FogPoint(const float *v)
8361 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8362 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8363 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8364 float FogHeightFade = r_refdef.fogheightfade;
8366 unsigned int fogmasktableindex;
8367 if (r_refdef.fogplaneviewabove)
8368 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8370 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8371 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8372 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8375 float RSurf_FogVertex(const float *v)
8377 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8378 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8379 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8380 float FogHeightFade = rsurface.fogheightfade;
8382 unsigned int fogmasktableindex;
8383 if (r_refdef.fogplaneviewabove)
8384 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8386 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8387 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8388 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8391 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8394 for (i = 0;i < numelements;i++)
8395 outelement3i[i] = inelement3i[i] + adjust;
8398 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8399 extern cvar_t gl_vbo;
8400 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8408 int surfacefirsttriangle;
8409 int surfacenumtriangles;
8410 int surfacefirstvertex;
8411 int surfaceendvertex;
8412 int surfacenumvertices;
8413 int batchnumvertices;
8414 int batchnumtriangles;
8418 qboolean dynamicvertex;
8422 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8424 q3shaderinfo_deform_t *deform;
8425 const msurface_t *surface, *firstsurface;
8426 r_vertexmesh_t *vertexmesh;
8427 if (!texturenumsurfaces)
8429 // find vertex range of this surface batch
8431 firstsurface = texturesurfacelist[0];
8432 firsttriangle = firstsurface->num_firsttriangle;
8433 batchnumvertices = 0;
8434 batchnumtriangles = 0;
8435 firstvertex = endvertex = firstsurface->num_firstvertex;
8436 for (i = 0;i < texturenumsurfaces;i++)
8438 surface = texturesurfacelist[i];
8439 if (surface != firstsurface + i)
8441 surfacefirstvertex = surface->num_firstvertex;
8442 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8443 surfacenumvertices = surface->num_vertices;
8444 surfacenumtriangles = surface->num_triangles;
8445 if (firstvertex > surfacefirstvertex)
8446 firstvertex = surfacefirstvertex;
8447 if (endvertex < surfaceendvertex)
8448 endvertex = surfaceendvertex;
8449 batchnumvertices += surfacenumvertices;
8450 batchnumtriangles += surfacenumtriangles;
8453 // we now know the vertex range used, and if there are any gaps in it
8454 rsurface.batchfirstvertex = firstvertex;
8455 rsurface.batchnumvertices = endvertex - firstvertex;
8456 rsurface.batchfirsttriangle = firsttriangle;
8457 rsurface.batchnumtriangles = batchnumtriangles;
8459 // this variable holds flags for which properties have been updated that
8460 // may require regenerating vertexmesh array...
8463 // check if any dynamic vertex processing must occur
8464 dynamicvertex = false;
8466 // if there is a chance of animated vertex colors, it's a dynamic batch
8467 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8469 dynamicvertex = true;
8470 batchneed |= BATCHNEED_NOGAPS;
8471 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8474 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8476 switch (deform->deform)
8479 case Q3DEFORM_PROJECTIONSHADOW:
8480 case Q3DEFORM_TEXT0:
8481 case Q3DEFORM_TEXT1:
8482 case Q3DEFORM_TEXT2:
8483 case Q3DEFORM_TEXT3:
8484 case Q3DEFORM_TEXT4:
8485 case Q3DEFORM_TEXT5:
8486 case Q3DEFORM_TEXT6:
8487 case Q3DEFORM_TEXT7:
8490 case Q3DEFORM_AUTOSPRITE:
8491 dynamicvertex = true;
8492 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8493 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8495 case Q3DEFORM_AUTOSPRITE2:
8496 dynamicvertex = true;
8497 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8498 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8500 case Q3DEFORM_NORMAL:
8501 dynamicvertex = true;
8502 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8503 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8506 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8507 break; // if wavefunc is a nop, ignore this transform
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;
8512 case Q3DEFORM_BULGE:
8513 dynamicvertex = true;
8514 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8515 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8518 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8519 break; // if wavefunc is a nop, ignore this transform
8520 dynamicvertex = true;
8521 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8522 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8526 switch(rsurface.texture->tcgen.tcgen)
8529 case Q3TCGEN_TEXTURE:
8531 case Q3TCGEN_LIGHTMAP:
8532 dynamicvertex = true;
8533 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8534 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8536 case Q3TCGEN_VECTOR:
8537 dynamicvertex = true;
8538 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8539 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8541 case Q3TCGEN_ENVIRONMENT:
8542 dynamicvertex = true;
8543 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8544 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8547 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8549 dynamicvertex = true;
8550 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8551 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8554 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8556 dynamicvertex = true;
8557 batchneed |= BATCHNEED_NOGAPS;
8558 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8561 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8563 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8564 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8565 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8566 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8567 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8568 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8569 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8572 // when the model data has no vertex buffer (dynamic mesh), we need to
8574 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8575 batchneed |= BATCHNEED_NOGAPS;
8577 // if needsupdate, we have to do a dynamic vertex batch for sure
8578 if (needsupdate & batchneed)
8579 dynamicvertex = true;
8581 // see if we need to build vertexmesh from arrays
8582 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8583 dynamicvertex = true;
8585 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8586 // also some drivers strongly dislike firstvertex
8587 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8588 dynamicvertex = true;
8590 rsurface.batchvertex3f = rsurface.modelvertex3f;
8591 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8592 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8593 rsurface.batchsvector3f = rsurface.modelsvector3f;
8594 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8595 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8596 rsurface.batchtvector3f = rsurface.modeltvector3f;
8597 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8598 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8599 rsurface.batchnormal3f = rsurface.modelnormal3f;
8600 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8601 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8602 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8603 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8604 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8605 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8606 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8607 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8608 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8609 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8610 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8611 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8612 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8613 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8614 rsurface.batchelement3i = rsurface.modelelement3i;
8615 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8616 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8617 rsurface.batchelement3s = rsurface.modelelement3s;
8618 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8619 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8621 // if any dynamic vertex processing has to occur in software, we copy the
8622 // entire surface list together before processing to rebase the vertices
8623 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8625 // if any gaps exist and we do not have a static vertex buffer, we have to
8626 // copy the surface list together to avoid wasting upload bandwidth on the
8627 // vertices in the gaps.
8629 // if gaps exist and we have a static vertex buffer, we still have to
8630 // combine the index buffer ranges into one dynamic index buffer.
8632 // in all cases we end up with data that can be drawn in one call.
8636 // static vertex data, just set pointers...
8637 rsurface.batchgeneratedvertex = false;
8638 // if there are gaps, we want to build a combined index buffer,
8639 // otherwise use the original static buffer with an appropriate offset
8642 // build a new triangle elements array for this batch
8643 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8644 rsurface.batchfirsttriangle = 0;
8646 for (i = 0;i < texturenumsurfaces;i++)
8648 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8649 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8650 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8651 numtriangles += surfacenumtriangles;
8653 rsurface.batchelement3i_indexbuffer = NULL;
8654 rsurface.batchelement3i_bufferoffset = 0;
8655 rsurface.batchelement3s = NULL;
8656 rsurface.batchelement3s_indexbuffer = NULL;
8657 rsurface.batchelement3s_bufferoffset = 0;
8658 if (endvertex <= 65536)
8660 // make a 16bit (unsigned short) index array if possible
8661 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8662 for (i = 0;i < numtriangles*3;i++)
8663 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8669 // something needs software processing, do it for real...
8670 // we only directly handle separate array data in this case and then
8671 // generate interleaved data if needed...
8672 rsurface.batchgeneratedvertex = true;
8674 // now copy the vertex data into a combined array and make an index array
8675 // (this is what Quake3 does all the time)
8676 //if (gaps || rsurface.batchfirstvertex)
8678 rsurface.batchvertex3fbuffer = NULL;
8679 rsurface.batchvertexmesh = NULL;
8680 rsurface.batchvertexmeshbuffer = NULL;
8681 rsurface.batchvertex3f = NULL;
8682 rsurface.batchvertex3f_vertexbuffer = NULL;
8683 rsurface.batchvertex3f_bufferoffset = 0;
8684 rsurface.batchsvector3f = NULL;
8685 rsurface.batchsvector3f_vertexbuffer = NULL;
8686 rsurface.batchsvector3f_bufferoffset = 0;
8687 rsurface.batchtvector3f = NULL;
8688 rsurface.batchtvector3f_vertexbuffer = NULL;
8689 rsurface.batchtvector3f_bufferoffset = 0;
8690 rsurface.batchnormal3f = NULL;
8691 rsurface.batchnormal3f_vertexbuffer = NULL;
8692 rsurface.batchnormal3f_bufferoffset = 0;
8693 rsurface.batchlightmapcolor4f = NULL;
8694 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8695 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8696 rsurface.batchtexcoordtexture2f = NULL;
8697 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8698 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8699 rsurface.batchtexcoordlightmap2f = NULL;
8700 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8701 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8702 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8703 rsurface.batchelement3i_indexbuffer = NULL;
8704 rsurface.batchelement3i_bufferoffset = 0;
8705 rsurface.batchelement3s = NULL;
8706 rsurface.batchelement3s_indexbuffer = NULL;
8707 rsurface.batchelement3s_bufferoffset = 0;
8708 // we'll only be setting up certain arrays as needed
8709 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8710 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8711 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8712 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8713 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8714 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8715 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8717 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8718 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8720 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8721 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8722 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8723 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8724 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8725 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8728 for (i = 0;i < texturenumsurfaces;i++)
8730 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8731 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8732 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8733 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8734 // copy only the data requested
8735 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8736 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8737 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8739 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8741 if (rsurface.batchvertex3f)
8742 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8744 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8746 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8748 if (rsurface.modelnormal3f)
8749 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8751 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8753 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8755 if (rsurface.modelsvector3f)
8757 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8758 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8762 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8763 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8766 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8768 if (rsurface.modellightmapcolor4f)
8769 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8771 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8773 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8775 if (rsurface.modeltexcoordtexture2f)
8776 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8778 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8780 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8782 if (rsurface.modeltexcoordlightmap2f)
8783 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8785 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8788 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8789 numvertices += surfacenumvertices;
8790 numtriangles += surfacenumtriangles;
8793 // generate a 16bit index array as well if possible
8794 // (in general, dynamic batches fit)
8795 if (numvertices <= 65536)
8797 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8798 for (i = 0;i < numtriangles*3;i++)
8799 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8802 // since we've copied everything, the batch now starts at 0
8803 rsurface.batchfirstvertex = 0;
8804 rsurface.batchnumvertices = batchnumvertices;
8805 rsurface.batchfirsttriangle = 0;
8806 rsurface.batchnumtriangles = batchnumtriangles;
8809 // q1bsp surfaces rendered in vertex color mode have to have colors
8810 // calculated based on lightstyles
8811 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8813 // generate color arrays for the surfaces in this list
8818 const unsigned char *lm;
8819 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8820 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8821 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8823 for (i = 0;i < texturenumsurfaces;i++)
8825 surface = texturesurfacelist[i];
8826 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8827 surfacenumvertices = surface->num_vertices;
8828 if (surface->lightmapinfo->samples)
8830 for (j = 0;j < surfacenumvertices;j++)
8832 lm = surface->lightmapinfo->samples + offsets[j];
8833 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8834 VectorScale(lm, scale, c);
8835 if (surface->lightmapinfo->styles[1] != 255)
8837 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8839 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8840 VectorMA(c, scale, lm, c);
8841 if (surface->lightmapinfo->styles[2] != 255)
8844 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8845 VectorMA(c, scale, lm, c);
8846 if (surface->lightmapinfo->styles[3] != 255)
8849 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8850 VectorMA(c, scale, lm, c);
8857 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);
8863 for (j = 0;j < surfacenumvertices;j++)
8865 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8872 // if vertices are deformed (sprite flares and things in maps, possibly
8873 // water waves, bulges and other deformations), modify the copied vertices
8875 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8877 switch (deform->deform)
8880 case Q3DEFORM_PROJECTIONSHADOW:
8881 case Q3DEFORM_TEXT0:
8882 case Q3DEFORM_TEXT1:
8883 case Q3DEFORM_TEXT2:
8884 case Q3DEFORM_TEXT3:
8885 case Q3DEFORM_TEXT4:
8886 case Q3DEFORM_TEXT5:
8887 case Q3DEFORM_TEXT6:
8888 case Q3DEFORM_TEXT7:
8891 case Q3DEFORM_AUTOSPRITE:
8892 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8893 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8894 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8895 VectorNormalize(newforward);
8896 VectorNormalize(newright);
8897 VectorNormalize(newup);
8898 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8899 // rsurface.batchvertex3f_vertexbuffer = NULL;
8900 // rsurface.batchvertex3f_bufferoffset = 0;
8901 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8902 // rsurface.batchsvector3f_vertexbuffer = NULL;
8903 // rsurface.batchsvector3f_bufferoffset = 0;
8904 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8905 // rsurface.batchtvector3f_vertexbuffer = NULL;
8906 // rsurface.batchtvector3f_bufferoffset = 0;
8907 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8908 // rsurface.batchnormal3f_vertexbuffer = NULL;
8909 // rsurface.batchnormal3f_bufferoffset = 0;
8910 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8911 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8912 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8913 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8914 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);
8915 // a single autosprite surface can contain multiple sprites...
8916 for (j = 0;j < batchnumvertices - 3;j += 4)
8918 VectorClear(center);
8919 for (i = 0;i < 4;i++)
8920 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8921 VectorScale(center, 0.25f, center);
8922 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8923 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8924 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8925 for (i = 0;i < 4;i++)
8927 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8928 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8931 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8932 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8933 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);
8935 case Q3DEFORM_AUTOSPRITE2:
8936 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8937 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8938 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8939 VectorNormalize(newforward);
8940 VectorNormalize(newright);
8941 VectorNormalize(newup);
8942 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8943 // rsurface.batchvertex3f_vertexbuffer = NULL;
8944 // rsurface.batchvertex3f_bufferoffset = 0;
8946 const float *v1, *v2;
8956 memset(shortest, 0, sizeof(shortest));
8957 // a single autosprite surface can contain multiple sprites...
8958 for (j = 0;j < batchnumvertices - 3;j += 4)
8960 VectorClear(center);
8961 for (i = 0;i < 4;i++)
8962 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8963 VectorScale(center, 0.25f, center);
8964 // find the two shortest edges, then use them to define the
8965 // axis vectors for rotating around the central axis
8966 for (i = 0;i < 6;i++)
8968 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8969 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8970 l = VectorDistance2(v1, v2);
8971 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8973 l += (1.0f / 1024.0f);
8974 if (shortest[0].length2 > l || i == 0)
8976 shortest[1] = shortest[0];
8977 shortest[0].length2 = l;
8978 shortest[0].v1 = v1;
8979 shortest[0].v2 = v2;
8981 else if (shortest[1].length2 > l || i == 1)
8983 shortest[1].length2 = l;
8984 shortest[1].v1 = v1;
8985 shortest[1].v2 = v2;
8988 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8989 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8990 // this calculates the right vector from the shortest edge
8991 // and the up vector from the edge midpoints
8992 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8993 VectorNormalize(right);
8994 VectorSubtract(end, start, up);
8995 VectorNormalize(up);
8996 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8997 VectorSubtract(rsurface.localvieworigin, center, forward);
8998 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8999 VectorNegate(forward, forward);
9000 VectorReflect(forward, 0, up, forward);
9001 VectorNormalize(forward);
9002 CrossProduct(up, forward, newright);
9003 VectorNormalize(newright);
9004 // rotate the quad around the up axis vector, this is made
9005 // especially easy by the fact we know the quad is flat,
9006 // so we only have to subtract the center position and
9007 // measure distance along the right vector, and then
9008 // multiply that by the newright vector and add back the
9010 // we also need to subtract the old position to undo the
9011 // displacement from the center, which we do with a
9012 // DotProduct, the subtraction/addition of center is also
9013 // optimized into DotProducts here
9014 l = DotProduct(right, center);
9015 for (i = 0;i < 4;i++)
9017 v1 = rsurface.batchvertex3f + 3*(j+i);
9018 f = DotProduct(right, v1) - l;
9019 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9023 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9025 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9026 // rsurface.batchnormal3f_vertexbuffer = NULL;
9027 // rsurface.batchnormal3f_bufferoffset = 0;
9028 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9030 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9032 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9033 // rsurface.batchsvector3f_vertexbuffer = NULL;
9034 // rsurface.batchsvector3f_bufferoffset = 0;
9035 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9036 // rsurface.batchtvector3f_vertexbuffer = NULL;
9037 // rsurface.batchtvector3f_bufferoffset = 0;
9038 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);
9041 case Q3DEFORM_NORMAL:
9042 // deform the normals to make reflections wavey
9043 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9044 rsurface.batchnormal3f_vertexbuffer = NULL;
9045 rsurface.batchnormal3f_bufferoffset = 0;
9046 for (j = 0;j < batchnumvertices;j++)
9049 float *normal = rsurface.batchnormal3f + 3*j;
9050 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9051 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9052 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9053 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9054 VectorNormalize(normal);
9056 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9058 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9059 // rsurface.batchsvector3f_vertexbuffer = NULL;
9060 // rsurface.batchsvector3f_bufferoffset = 0;
9061 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9062 // rsurface.batchtvector3f_vertexbuffer = NULL;
9063 // rsurface.batchtvector3f_bufferoffset = 0;
9064 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);
9068 // deform vertex array to make wavey water and flags and such
9069 waveparms[0] = deform->waveparms[0];
9070 waveparms[1] = deform->waveparms[1];
9071 waveparms[2] = deform->waveparms[2];
9072 waveparms[3] = deform->waveparms[3];
9073 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9074 break; // if wavefunc is a nop, don't make a dynamic vertex array
9075 // this is how a divisor of vertex influence on deformation
9076 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9077 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9078 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9079 // rsurface.batchvertex3f_vertexbuffer = NULL;
9080 // rsurface.batchvertex3f_bufferoffset = 0;
9081 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9082 // rsurface.batchnormal3f_vertexbuffer = NULL;
9083 // rsurface.batchnormal3f_bufferoffset = 0;
9084 for (j = 0;j < batchnumvertices;j++)
9086 // if the wavefunc depends on time, evaluate it per-vertex
9089 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9090 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9092 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9094 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9095 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9096 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9098 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9099 // rsurface.batchsvector3f_vertexbuffer = NULL;
9100 // rsurface.batchsvector3f_bufferoffset = 0;
9101 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9102 // rsurface.batchtvector3f_vertexbuffer = NULL;
9103 // rsurface.batchtvector3f_bufferoffset = 0;
9104 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);
9107 case Q3DEFORM_BULGE:
9108 // deform vertex array to make the surface have moving bulges
9109 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9110 // rsurface.batchvertex3f_vertexbuffer = NULL;
9111 // rsurface.batchvertex3f_bufferoffset = 0;
9112 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9113 // rsurface.batchnormal3f_vertexbuffer = NULL;
9114 // rsurface.batchnormal3f_bufferoffset = 0;
9115 for (j = 0;j < batchnumvertices;j++)
9117 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9118 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9120 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9121 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9122 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9124 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9125 // rsurface.batchsvector3f_vertexbuffer = NULL;
9126 // rsurface.batchsvector3f_bufferoffset = 0;
9127 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9128 // rsurface.batchtvector3f_vertexbuffer = NULL;
9129 // rsurface.batchtvector3f_bufferoffset = 0;
9130 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);
9134 // deform vertex array
9135 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9136 break; // if wavefunc is a nop, don't make a dynamic vertex array
9137 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9138 VectorScale(deform->parms, scale, waveparms);
9139 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9140 // rsurface.batchvertex3f_vertexbuffer = NULL;
9141 // rsurface.batchvertex3f_bufferoffset = 0;
9142 for (j = 0;j < batchnumvertices;j++)
9143 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9148 // generate texcoords based on the chosen texcoord source
9149 switch(rsurface.texture->tcgen.tcgen)
9152 case Q3TCGEN_TEXTURE:
9154 case Q3TCGEN_LIGHTMAP:
9155 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9156 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9157 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9158 if (rsurface.batchtexcoordlightmap2f)
9159 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9161 case Q3TCGEN_VECTOR:
9162 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9163 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9164 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9165 for (j = 0;j < batchnumvertices;j++)
9167 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9168 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9171 case Q3TCGEN_ENVIRONMENT:
9172 // make environment reflections using a spheremap
9173 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9174 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9175 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9176 for (j = 0;j < batchnumvertices;j++)
9178 // identical to Q3A's method, but executed in worldspace so
9179 // carried models can be shiny too
9181 float viewer[3], d, reflected[3], worldreflected[3];
9183 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9184 // VectorNormalize(viewer);
9186 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9188 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9189 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9190 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9191 // note: this is proportinal to viewer, so we can normalize later
9193 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9194 VectorNormalize(worldreflected);
9196 // note: this sphere map only uses world x and z!
9197 // so positive and negative y will LOOK THE SAME.
9198 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9199 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9203 // the only tcmod that needs software vertex processing is turbulent, so
9204 // check for it here and apply the changes if needed
9205 // and we only support that as the first one
9206 // (handling a mixture of turbulent and other tcmods would be problematic
9207 // without punting it entirely to a software path)
9208 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9210 amplitude = rsurface.texture->tcmods[0].parms[1];
9211 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9212 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9213 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9214 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9215 for (j = 0;j < batchnumvertices;j++)
9217 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);
9218 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9222 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9224 // convert the modified arrays to vertex structs
9225 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9226 // rsurface.batchvertexmeshbuffer = NULL;
9227 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9228 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9229 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9230 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9231 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9232 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9233 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9235 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9237 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9238 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9241 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9242 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9243 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9244 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9245 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9246 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9247 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9248 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9249 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9253 void RSurf_DrawBatch(void)
9255 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9256 // through the pipeline, killing it earlier in the pipeline would have
9257 // per-surface overhead rather than per-batch overhead, so it's best to
9258 // reject it here, before it hits glDraw.
9259 if (rsurface.batchnumtriangles == 0)
9262 // batch debugging code
9263 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9269 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9270 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9273 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9275 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9277 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9278 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);
9285 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);
9288 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9290 // pick the closest matching water plane
9291 int planeindex, vertexindex, bestplaneindex = -1;
9295 r_waterstate_waterplane_t *p;
9296 qboolean prepared = false;
9298 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9300 if(p->camera_entity != rsurface.texture->camera_entity)
9305 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9307 if(rsurface.batchnumvertices == 0)
9310 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9312 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9313 d += fabs(PlaneDiff(vert, &p->plane));
9315 if (bestd > d || bestplaneindex < 0)
9318 bestplaneindex = planeindex;
9321 return bestplaneindex;
9322 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9323 // this situation though, as it might be better to render single larger
9324 // batches with useless stuff (backface culled for example) than to
9325 // render multiple smaller batches
9328 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9331 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9332 rsurface.passcolor4f_vertexbuffer = 0;
9333 rsurface.passcolor4f_bufferoffset = 0;
9334 for (i = 0;i < rsurface.batchnumvertices;i++)
9335 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9338 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9345 if (rsurface.passcolor4f)
9347 // generate color arrays
9348 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9349 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9350 rsurface.passcolor4f_vertexbuffer = 0;
9351 rsurface.passcolor4f_bufferoffset = 0;
9352 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)
9354 f = RSurf_FogVertex(v);
9363 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9364 rsurface.passcolor4f_vertexbuffer = 0;
9365 rsurface.passcolor4f_bufferoffset = 0;
9366 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9368 f = RSurf_FogVertex(v);
9377 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9384 if (!rsurface.passcolor4f)
9386 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9387 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9388 rsurface.passcolor4f_vertexbuffer = 0;
9389 rsurface.passcolor4f_bufferoffset = 0;
9390 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)
9392 f = RSurf_FogVertex(v);
9393 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9394 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9395 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9400 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9405 if (!rsurface.passcolor4f)
9407 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9408 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9409 rsurface.passcolor4f_vertexbuffer = 0;
9410 rsurface.passcolor4f_bufferoffset = 0;
9411 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9420 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9425 if (!rsurface.passcolor4f)
9427 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9428 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9429 rsurface.passcolor4f_vertexbuffer = 0;
9430 rsurface.passcolor4f_bufferoffset = 0;
9431 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9433 c2[0] = c[0] + r_refdef.scene.ambient;
9434 c2[1] = c[1] + r_refdef.scene.ambient;
9435 c2[2] = c[2] + r_refdef.scene.ambient;
9440 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9443 rsurface.passcolor4f = NULL;
9444 rsurface.passcolor4f_vertexbuffer = 0;
9445 rsurface.passcolor4f_bufferoffset = 0;
9446 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9447 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9448 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9449 GL_Color(r, g, b, a);
9450 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9454 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9456 // TODO: optimize applyfog && applycolor case
9457 // just apply fog if necessary, and tint the fog color array if necessary
9458 rsurface.passcolor4f = NULL;
9459 rsurface.passcolor4f_vertexbuffer = 0;
9460 rsurface.passcolor4f_bufferoffset = 0;
9461 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9462 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9463 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9464 GL_Color(r, g, b, a);
9468 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9471 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9472 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9473 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9474 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9475 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9476 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9477 GL_Color(r, g, b, a);
9481 static void RSurf_DrawBatch_GL11_ClampColor(void)
9486 if (!rsurface.passcolor4f)
9488 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9490 c2[0] = bound(0.0f, c1[0], 1.0f);
9491 c2[1] = bound(0.0f, c1[1], 1.0f);
9492 c2[2] = bound(0.0f, c1[2], 1.0f);
9493 c2[3] = bound(0.0f, c1[3], 1.0f);
9497 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9507 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9508 rsurface.passcolor4f_vertexbuffer = 0;
9509 rsurface.passcolor4f_bufferoffset = 0;
9510 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)
9512 f = -DotProduct(r_refdef.view.forward, n);
9514 f = f * 0.85 + 0.15; // work around so stuff won't get black
9515 f *= r_refdef.lightmapintensity;
9516 Vector4Set(c, f, f, f, 1);
9520 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9522 RSurf_DrawBatch_GL11_ApplyFakeLight();
9523 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9524 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9525 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9526 GL_Color(r, g, b, a);
9530 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9538 vec3_t ambientcolor;
9539 vec3_t diffusecolor;
9543 VectorCopy(rsurface.modellight_lightdir, lightdir);
9544 f = 0.5f * r_refdef.lightmapintensity;
9545 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9546 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9547 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9548 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9549 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9550 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9552 if (VectorLength2(diffusecolor) > 0)
9554 // q3-style directional shading
9555 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9556 rsurface.passcolor4f_vertexbuffer = 0;
9557 rsurface.passcolor4f_bufferoffset = 0;
9558 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)
9560 if ((f = DotProduct(n, lightdir)) > 0)
9561 VectorMA(ambientcolor, f, diffusecolor, c);
9563 VectorCopy(ambientcolor, c);
9570 *applycolor = false;
9574 *r = ambientcolor[0];
9575 *g = ambientcolor[1];
9576 *b = ambientcolor[2];
9577 rsurface.passcolor4f = NULL;
9578 rsurface.passcolor4f_vertexbuffer = 0;
9579 rsurface.passcolor4f_bufferoffset = 0;
9583 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9585 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9586 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9587 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9588 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9589 GL_Color(r, g, b, a);
9593 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9601 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9602 rsurface.passcolor4f_vertexbuffer = 0;
9603 rsurface.passcolor4f_bufferoffset = 0;
9605 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9607 f = 1 - RSurf_FogVertex(v);
9615 void RSurf_SetupDepthAndCulling(void)
9617 // submodels are biased to avoid z-fighting with world surfaces that they
9618 // may be exactly overlapping (avoids z-fighting artifacts on certain
9619 // doors and things in Quake maps)
9620 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9621 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9622 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9623 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9626 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9628 // transparent sky would be ridiculous
9629 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9631 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9632 skyrenderlater = true;
9633 RSurf_SetupDepthAndCulling();
9635 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9636 // skymasking on them, and Quake3 never did sky masking (unlike
9637 // software Quake and software Quake2), so disable the sky masking
9638 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9639 // and skymasking also looks very bad when noclipping outside the
9640 // level, so don't use it then either.
9641 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9643 R_Mesh_ResetTextureState();
9644 if (skyrendermasked)
9646 R_SetupShader_DepthOrShadow(false);
9647 // depth-only (masking)
9648 GL_ColorMask(0,0,0,0);
9649 // just to make sure that braindead drivers don't draw
9650 // anything despite that colormask...
9651 GL_BlendFunc(GL_ZERO, GL_ONE);
9652 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9653 if (rsurface.batchvertex3fbuffer)
9654 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9656 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9660 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9662 GL_BlendFunc(GL_ONE, GL_ZERO);
9663 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9664 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9665 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9668 if (skyrendermasked)
9669 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9671 R_Mesh_ResetTextureState();
9672 GL_Color(1, 1, 1, 1);
9675 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9676 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9677 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9679 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9683 // render screenspace normalmap to texture
9685 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9689 // bind lightmap texture
9691 // water/refraction/reflection/camera surfaces have to be handled specially
9692 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9694 int start, end, startplaneindex;
9695 for (start = 0;start < texturenumsurfaces;start = end)
9697 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9698 if(startplaneindex < 0)
9700 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9701 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9705 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9707 // now that we have a batch using the same planeindex, render it
9708 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9710 // render water or distortion background
9712 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);
9714 // blend surface on top
9715 GL_DepthMask(false);
9716 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9719 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9721 // render surface with reflection texture as input
9722 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9723 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);
9730 // render surface batch normally
9731 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9732 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);
9736 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9738 // OpenGL 1.3 path - anything not completely ancient
9739 qboolean applycolor;
9742 const texturelayer_t *layer;
9743 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);
9744 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9746 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9749 int layertexrgbscale;
9750 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9752 if (layerindex == 0)
9756 GL_AlphaTest(false);
9757 GL_DepthFunc(GL_EQUAL);
9760 GL_DepthMask(layer->depthmask && writedepth);
9761 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9762 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9764 layertexrgbscale = 4;
9765 VectorScale(layer->color, 0.25f, layercolor);
9767 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9769 layertexrgbscale = 2;
9770 VectorScale(layer->color, 0.5f, layercolor);
9774 layertexrgbscale = 1;
9775 VectorScale(layer->color, 1.0f, layercolor);
9777 layercolor[3] = layer->color[3];
9778 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9779 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9780 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9781 switch (layer->type)
9783 case TEXTURELAYERTYPE_LITTEXTURE:
9784 // single-pass lightmapped texture with 2x rgbscale
9785 R_Mesh_TexBind(0, r_texture_white);
9786 R_Mesh_TexMatrix(0, NULL);
9787 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9788 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9789 R_Mesh_TexBind(1, layer->texture);
9790 R_Mesh_TexMatrix(1, &layer->texmatrix);
9791 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9792 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9793 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9794 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9795 else if (FAKELIGHT_ENABLED)
9796 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9797 else if (rsurface.uselightmaptexture)
9798 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9800 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9802 case TEXTURELAYERTYPE_TEXTURE:
9803 // singletexture unlit texture with transparency support
9804 R_Mesh_TexBind(0, layer->texture);
9805 R_Mesh_TexMatrix(0, &layer->texmatrix);
9806 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9807 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9808 R_Mesh_TexBind(1, 0);
9809 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9810 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9812 case TEXTURELAYERTYPE_FOG:
9813 // singletexture fogging
9816 R_Mesh_TexBind(0, layer->texture);
9817 R_Mesh_TexMatrix(0, &layer->texmatrix);
9818 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9819 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9823 R_Mesh_TexBind(0, 0);
9824 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9826 R_Mesh_TexBind(1, 0);
9827 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9828 // generate a color array for the fog pass
9829 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9830 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9834 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9837 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9839 GL_DepthFunc(GL_LEQUAL);
9840 GL_AlphaTest(false);
9844 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9846 // OpenGL 1.1 - crusty old voodoo path
9849 const texturelayer_t *layer;
9850 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);
9851 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9853 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9855 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9857 if (layerindex == 0)
9861 GL_AlphaTest(false);
9862 GL_DepthFunc(GL_EQUAL);
9865 GL_DepthMask(layer->depthmask && writedepth);
9866 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9867 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9868 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9869 switch (layer->type)
9871 case TEXTURELAYERTYPE_LITTEXTURE:
9872 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9874 // two-pass lit texture with 2x rgbscale
9875 // first the lightmap pass
9876 R_Mesh_TexBind(0, r_texture_white);
9877 R_Mesh_TexMatrix(0, NULL);
9878 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9879 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9880 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9881 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9882 else if (FAKELIGHT_ENABLED)
9883 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9884 else if (rsurface.uselightmaptexture)
9885 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9887 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9888 // then apply the texture to it
9889 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9890 R_Mesh_TexBind(0, layer->texture);
9891 R_Mesh_TexMatrix(0, &layer->texmatrix);
9892 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9893 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9894 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);
9898 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9899 R_Mesh_TexBind(0, layer->texture);
9900 R_Mesh_TexMatrix(0, &layer->texmatrix);
9901 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9902 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9903 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9904 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);
9906 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);
9909 case TEXTURELAYERTYPE_TEXTURE:
9910 // singletexture unlit texture with transparency support
9911 R_Mesh_TexBind(0, layer->texture);
9912 R_Mesh_TexMatrix(0, &layer->texmatrix);
9913 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9914 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9915 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);
9917 case TEXTURELAYERTYPE_FOG:
9918 // singletexture fogging
9921 R_Mesh_TexBind(0, layer->texture);
9922 R_Mesh_TexMatrix(0, &layer->texmatrix);
9923 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9924 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9928 R_Mesh_TexBind(0, 0);
9929 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9931 // generate a color array for the fog pass
9932 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9933 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9937 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9940 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9942 GL_DepthFunc(GL_LEQUAL);
9943 GL_AlphaTest(false);
9947 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9951 r_vertexgeneric_t *batchvertex;
9954 // R_Mesh_ResetTextureState();
9955 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9957 if(rsurface.texture && rsurface.texture->currentskinframe)
9959 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9960 c[3] *= rsurface.texture->currentalpha;
9970 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9972 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9973 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9974 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9977 // brighten it up (as texture value 127 means "unlit")
9978 c[0] *= 2 * r_refdef.view.colorscale;
9979 c[1] *= 2 * r_refdef.view.colorscale;
9980 c[2] *= 2 * r_refdef.view.colorscale;
9982 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9983 c[3] *= r_wateralpha.value;
9985 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9987 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9988 GL_DepthMask(false);
9990 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9992 GL_BlendFunc(GL_ONE, GL_ONE);
9993 GL_DepthMask(false);
9995 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9997 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9998 GL_DepthMask(false);
10000 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10002 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10003 GL_DepthMask(false);
10007 GL_BlendFunc(GL_ONE, GL_ZERO);
10008 GL_DepthMask(writedepth);
10011 if (r_showsurfaces.integer == 3)
10013 rsurface.passcolor4f = NULL;
10015 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10017 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10019 rsurface.passcolor4f = NULL;
10020 rsurface.passcolor4f_vertexbuffer = 0;
10021 rsurface.passcolor4f_bufferoffset = 0;
10023 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10025 qboolean applycolor = true;
10028 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10030 r_refdef.lightmapintensity = 1;
10031 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10032 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10034 else if (FAKELIGHT_ENABLED)
10036 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10038 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10039 RSurf_DrawBatch_GL11_ApplyFakeLight();
10040 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10044 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10046 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10047 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10048 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10051 if(!rsurface.passcolor4f)
10052 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10054 RSurf_DrawBatch_GL11_ApplyAmbient();
10055 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10056 if(r_refdef.fogenabled)
10057 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10058 RSurf_DrawBatch_GL11_ClampColor();
10060 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10061 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10064 else if (!r_refdef.view.showdebug)
10066 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10067 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10068 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10070 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10071 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10073 R_Mesh_PrepareVertices_Generic_Unlock();
10076 else if (r_showsurfaces.integer == 4)
10078 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10079 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10080 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10082 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10083 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10084 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10086 R_Mesh_PrepareVertices_Generic_Unlock();
10089 else if (r_showsurfaces.integer == 2)
10092 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10093 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10094 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10096 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10097 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10098 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10099 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10100 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10101 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10102 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10104 R_Mesh_PrepareVertices_Generic_Unlock();
10105 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10109 int texturesurfaceindex;
10111 const msurface_t *surface;
10112 float surfacecolor4f[4];
10113 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10114 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10116 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10118 surface = texturesurfacelist[texturesurfaceindex];
10119 k = (int)(((size_t)surface) / sizeof(msurface_t));
10120 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10121 for (j = 0;j < surface->num_vertices;j++)
10123 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10124 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10128 R_Mesh_PrepareVertices_Generic_Unlock();
10133 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10136 RSurf_SetupDepthAndCulling();
10137 if (r_showsurfaces.integer)
10139 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10142 switch (vid.renderpath)
10144 case RENDERPATH_GL20:
10145 case RENDERPATH_D3D9:
10146 case RENDERPATH_D3D10:
10147 case RENDERPATH_D3D11:
10148 case RENDERPATH_SOFT:
10149 case RENDERPATH_GLES2:
10150 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10152 case RENDERPATH_GL13:
10153 case RENDERPATH_GLES1:
10154 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10156 case RENDERPATH_GL11:
10157 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10163 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10166 RSurf_SetupDepthAndCulling();
10167 if (r_showsurfaces.integer)
10169 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10172 switch (vid.renderpath)
10174 case RENDERPATH_GL20:
10175 case RENDERPATH_D3D9:
10176 case RENDERPATH_D3D10:
10177 case RENDERPATH_D3D11:
10178 case RENDERPATH_SOFT:
10179 case RENDERPATH_GLES2:
10180 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10182 case RENDERPATH_GL13:
10183 case RENDERPATH_GLES1:
10184 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10186 case RENDERPATH_GL11:
10187 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10193 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10196 int texturenumsurfaces, endsurface;
10197 texture_t *texture;
10198 const msurface_t *surface;
10199 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10201 // if the model is static it doesn't matter what value we give for
10202 // wantnormals and wanttangents, so this logic uses only rules applicable
10203 // to a model, knowing that they are meaningless otherwise
10204 if (ent == r_refdef.scene.worldentity)
10205 RSurf_ActiveWorldEntity();
10206 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10207 RSurf_ActiveModelEntity(ent, false, false, false);
10210 switch (vid.renderpath)
10212 case RENDERPATH_GL20:
10213 case RENDERPATH_D3D9:
10214 case RENDERPATH_D3D10:
10215 case RENDERPATH_D3D11:
10216 case RENDERPATH_SOFT:
10217 case RENDERPATH_GLES2:
10218 RSurf_ActiveModelEntity(ent, true, true, false);
10220 case RENDERPATH_GL11:
10221 case RENDERPATH_GL13:
10222 case RENDERPATH_GLES1:
10223 RSurf_ActiveModelEntity(ent, true, false, false);
10228 if (r_transparentdepthmasking.integer)
10230 qboolean setup = false;
10231 for (i = 0;i < numsurfaces;i = j)
10234 surface = rsurface.modelsurfaces + surfacelist[i];
10235 texture = surface->texture;
10236 rsurface.texture = R_GetCurrentTexture(texture);
10237 rsurface.lightmaptexture = NULL;
10238 rsurface.deluxemaptexture = NULL;
10239 rsurface.uselightmaptexture = false;
10240 // scan ahead until we find a different texture
10241 endsurface = min(i + 1024, numsurfaces);
10242 texturenumsurfaces = 0;
10243 texturesurfacelist[texturenumsurfaces++] = surface;
10244 for (;j < endsurface;j++)
10246 surface = rsurface.modelsurfaces + surfacelist[j];
10247 if (texture != surface->texture)
10249 texturesurfacelist[texturenumsurfaces++] = surface;
10251 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10253 // render the range of surfaces as depth
10257 GL_ColorMask(0,0,0,0);
10259 GL_DepthTest(true);
10260 GL_BlendFunc(GL_ONE, GL_ZERO);
10261 GL_DepthMask(true);
10262 // R_Mesh_ResetTextureState();
10263 R_SetupShader_DepthOrShadow(false);
10265 RSurf_SetupDepthAndCulling();
10266 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10267 if (rsurface.batchvertex3fbuffer)
10268 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10270 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10274 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10277 for (i = 0;i < numsurfaces;i = j)
10280 surface = rsurface.modelsurfaces + surfacelist[i];
10281 texture = surface->texture;
10282 rsurface.texture = R_GetCurrentTexture(texture);
10283 // scan ahead until we find a different texture
10284 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10285 texturenumsurfaces = 0;
10286 texturesurfacelist[texturenumsurfaces++] = surface;
10287 if(FAKELIGHT_ENABLED)
10289 rsurface.lightmaptexture = NULL;
10290 rsurface.deluxemaptexture = NULL;
10291 rsurface.uselightmaptexture = false;
10292 for (;j < endsurface;j++)
10294 surface = rsurface.modelsurfaces + surfacelist[j];
10295 if (texture != surface->texture)
10297 texturesurfacelist[texturenumsurfaces++] = surface;
10302 rsurface.lightmaptexture = surface->lightmaptexture;
10303 rsurface.deluxemaptexture = surface->deluxemaptexture;
10304 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10305 for (;j < endsurface;j++)
10307 surface = rsurface.modelsurfaces + surfacelist[j];
10308 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10310 texturesurfacelist[texturenumsurfaces++] = surface;
10313 // render the range of surfaces
10314 if (ent == r_refdef.scene.worldentity)
10315 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10317 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10319 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10322 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10324 // transparent surfaces get pushed off into the transparent queue
10325 int surfacelistindex;
10326 const msurface_t *surface;
10327 vec3_t tempcenter, center;
10328 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10330 surface = texturesurfacelist[surfacelistindex];
10331 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10332 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10333 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10334 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10335 if (queueentity->transparent_offset) // transparent offset
10337 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10338 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10339 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10341 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10345 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10347 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10349 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10351 RSurf_SetupDepthAndCulling();
10352 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10353 if (rsurface.batchvertex3fbuffer)
10354 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10356 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10360 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10362 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10365 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10368 if (!rsurface.texture->currentnumlayers)
10370 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10371 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10373 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10375 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10376 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10377 else if (!rsurface.texture->currentnumlayers)
10379 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10381 // in the deferred case, transparent surfaces were queued during prepass
10382 if (!r_shadow_usingdeferredprepass)
10383 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10387 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10388 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10393 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10396 texture_t *texture;
10397 R_FrameData_SetMark();
10398 // break the surface list down into batches by texture and use of lightmapping
10399 for (i = 0;i < numsurfaces;i = j)
10402 // texture is the base texture pointer, rsurface.texture is the
10403 // current frame/skin the texture is directing us to use (for example
10404 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10405 // use skin 1 instead)
10406 texture = surfacelist[i]->texture;
10407 rsurface.texture = R_GetCurrentTexture(texture);
10408 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10410 // if this texture is not the kind we want, skip ahead to the next one
10411 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10415 if(FAKELIGHT_ENABLED || depthonly || prepass)
10417 rsurface.lightmaptexture = NULL;
10418 rsurface.deluxemaptexture = NULL;
10419 rsurface.uselightmaptexture = false;
10420 // simply scan ahead until we find a different texture or lightmap state
10421 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10426 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10427 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10428 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10429 // simply scan ahead until we find a different texture or lightmap state
10430 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10433 // render the range of surfaces
10434 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10436 R_FrameData_ReturnToMark();
10439 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10443 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10446 if (!rsurface.texture->currentnumlayers)
10448 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10449 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10451 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10453 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10454 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10455 else if (!rsurface.texture->currentnumlayers)
10457 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10459 // in the deferred case, transparent surfaces were queued during prepass
10460 if (!r_shadow_usingdeferredprepass)
10461 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10465 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10466 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10471 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10474 texture_t *texture;
10475 R_FrameData_SetMark();
10476 // break the surface list down into batches by texture and use of lightmapping
10477 for (i = 0;i < numsurfaces;i = j)
10480 // texture is the base texture pointer, rsurface.texture is the
10481 // current frame/skin the texture is directing us to use (for example
10482 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10483 // use skin 1 instead)
10484 texture = surfacelist[i]->texture;
10485 rsurface.texture = R_GetCurrentTexture(texture);
10486 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10488 // if this texture is not the kind we want, skip ahead to the next one
10489 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10493 if(FAKELIGHT_ENABLED || depthonly || prepass)
10495 rsurface.lightmaptexture = NULL;
10496 rsurface.deluxemaptexture = NULL;
10497 rsurface.uselightmaptexture = false;
10498 // simply scan ahead until we find a different texture or lightmap state
10499 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10504 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10505 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10506 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10507 // simply scan ahead until we find a different texture or lightmap state
10508 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10511 // render the range of surfaces
10512 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10514 R_FrameData_ReturnToMark();
10517 float locboxvertex3f[6*4*3] =
10519 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10520 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10521 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10522 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10523 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10524 1,0,0, 0,0,0, 0,1,0, 1,1,0
10527 unsigned short locboxelements[6*2*3] =
10532 12,13,14, 12,14,15,
10533 16,17,18, 16,18,19,
10537 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10540 cl_locnode_t *loc = (cl_locnode_t *)ent;
10542 float vertex3f[6*4*3];
10544 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10545 GL_DepthMask(false);
10546 GL_DepthRange(0, 1);
10547 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10548 GL_DepthTest(true);
10549 GL_CullFace(GL_NONE);
10550 R_EntityMatrix(&identitymatrix);
10552 // R_Mesh_ResetTextureState();
10554 i = surfacelist[0];
10555 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10556 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10557 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10558 surfacelist[0] < 0 ? 0.5f : 0.125f);
10560 if (VectorCompare(loc->mins, loc->maxs))
10562 VectorSet(size, 2, 2, 2);
10563 VectorMA(loc->mins, -0.5f, size, mins);
10567 VectorCopy(loc->mins, mins);
10568 VectorSubtract(loc->maxs, loc->mins, size);
10571 for (i = 0;i < 6*4*3;)
10572 for (j = 0;j < 3;j++, i++)
10573 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10575 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10576 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10577 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10580 void R_DrawLocs(void)
10583 cl_locnode_t *loc, *nearestloc;
10585 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10586 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10588 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10589 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10593 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10595 if (decalsystem->decals)
10596 Mem_Free(decalsystem->decals);
10597 memset(decalsystem, 0, sizeof(*decalsystem));
10600 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)
10603 tridecal_t *decals;
10606 // expand or initialize the system
10607 if (decalsystem->maxdecals <= decalsystem->numdecals)
10609 decalsystem_t old = *decalsystem;
10610 qboolean useshortelements;
10611 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10612 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10613 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)));
10614 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10615 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10616 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10617 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10618 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10619 if (decalsystem->numdecals)
10620 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10622 Mem_Free(old.decals);
10623 for (i = 0;i < decalsystem->maxdecals*3;i++)
10624 decalsystem->element3i[i] = i;
10625 if (useshortelements)
10626 for (i = 0;i < decalsystem->maxdecals*3;i++)
10627 decalsystem->element3s[i] = i;
10630 // grab a decal and search for another free slot for the next one
10631 decals = decalsystem->decals;
10632 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10633 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10635 decalsystem->freedecal = i;
10636 if (decalsystem->numdecals <= i)
10637 decalsystem->numdecals = i + 1;
10639 // initialize the decal
10641 decal->triangleindex = triangleindex;
10642 decal->surfaceindex = surfaceindex;
10643 decal->decalsequence = decalsequence;
10644 decal->color4f[0][0] = c0[0];
10645 decal->color4f[0][1] = c0[1];
10646 decal->color4f[0][2] = c0[2];
10647 decal->color4f[0][3] = 1;
10648 decal->color4f[1][0] = c1[0];
10649 decal->color4f[1][1] = c1[1];
10650 decal->color4f[1][2] = c1[2];
10651 decal->color4f[1][3] = 1;
10652 decal->color4f[2][0] = c2[0];
10653 decal->color4f[2][1] = c2[1];
10654 decal->color4f[2][2] = c2[2];
10655 decal->color4f[2][3] = 1;
10656 decal->vertex3f[0][0] = v0[0];
10657 decal->vertex3f[0][1] = v0[1];
10658 decal->vertex3f[0][2] = v0[2];
10659 decal->vertex3f[1][0] = v1[0];
10660 decal->vertex3f[1][1] = v1[1];
10661 decal->vertex3f[1][2] = v1[2];
10662 decal->vertex3f[2][0] = v2[0];
10663 decal->vertex3f[2][1] = v2[1];
10664 decal->vertex3f[2][2] = v2[2];
10665 decal->texcoord2f[0][0] = t0[0];
10666 decal->texcoord2f[0][1] = t0[1];
10667 decal->texcoord2f[1][0] = t1[0];
10668 decal->texcoord2f[1][1] = t1[1];
10669 decal->texcoord2f[2][0] = t2[0];
10670 decal->texcoord2f[2][1] = t2[1];
10671 TriangleNormal(v0, v1, v2, decal->plane);
10672 VectorNormalize(decal->plane);
10673 decal->plane[3] = DotProduct(v0, decal->plane);
10676 extern cvar_t cl_decals_bias;
10677 extern cvar_t cl_decals_models;
10678 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10679 // baseparms, parms, temps
10680 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)
10685 const float *vertex3f;
10686 const float *normal3f;
10688 float points[2][9][3];
10695 e = rsurface.modelelement3i + 3*triangleindex;
10697 vertex3f = rsurface.modelvertex3f;
10698 normal3f = rsurface.modelnormal3f;
10702 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10704 index = 3*e[cornerindex];
10705 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10710 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10712 index = 3*e[cornerindex];
10713 VectorCopy(vertex3f + index, v[cornerindex]);
10718 //TriangleNormal(v[0], v[1], v[2], normal);
10719 //if (DotProduct(normal, localnormal) < 0.0f)
10721 // clip by each of the box planes formed from the projection matrix
10722 // if anything survives, we emit the decal
10723 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]);
10726 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]);
10729 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]);
10732 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]);
10735 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]);
10738 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]);
10741 // some part of the triangle survived, so we have to accept it...
10744 // dynamic always uses the original triangle
10746 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10748 index = 3*e[cornerindex];
10749 VectorCopy(vertex3f + index, v[cornerindex]);
10752 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10754 // convert vertex positions to texcoords
10755 Matrix4x4_Transform(projection, v[cornerindex], temp);
10756 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10757 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10758 // calculate distance fade from the projection origin
10759 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10760 f = bound(0.0f, f, 1.0f);
10761 c[cornerindex][0] = r * f;
10762 c[cornerindex][1] = g * f;
10763 c[cornerindex][2] = b * f;
10764 c[cornerindex][3] = 1.0f;
10765 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10768 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);
10770 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10771 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);
10773 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)
10775 matrix4x4_t projection;
10776 decalsystem_t *decalsystem;
10779 const msurface_t *surface;
10780 const msurface_t *surfaces;
10781 const int *surfacelist;
10782 const texture_t *texture;
10784 int numsurfacelist;
10785 int surfacelistindex;
10788 float localorigin[3];
10789 float localnormal[3];
10790 float localmins[3];
10791 float localmaxs[3];
10794 float planes[6][4];
10797 int bih_triangles_count;
10798 int bih_triangles[256];
10799 int bih_surfaces[256];
10801 decalsystem = &ent->decalsystem;
10802 model = ent->model;
10803 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10805 R_DecalSystem_Reset(&ent->decalsystem);
10809 if (!model->brush.data_leafs && !cl_decals_models.integer)
10811 if (decalsystem->model)
10812 R_DecalSystem_Reset(decalsystem);
10816 if (decalsystem->model != model)
10817 R_DecalSystem_Reset(decalsystem);
10818 decalsystem->model = model;
10820 RSurf_ActiveModelEntity(ent, true, false, false);
10822 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10823 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10824 VectorNormalize(localnormal);
10825 localsize = worldsize*rsurface.inversematrixscale;
10826 localmins[0] = localorigin[0] - localsize;
10827 localmins[1] = localorigin[1] - localsize;
10828 localmins[2] = localorigin[2] - localsize;
10829 localmaxs[0] = localorigin[0] + localsize;
10830 localmaxs[1] = localorigin[1] + localsize;
10831 localmaxs[2] = localorigin[2] + localsize;
10833 //VectorCopy(localnormal, planes[4]);
10834 //VectorVectors(planes[4], planes[2], planes[0]);
10835 AnglesFromVectors(angles, localnormal, NULL, false);
10836 AngleVectors(angles, planes[0], planes[2], planes[4]);
10837 VectorNegate(planes[0], planes[1]);
10838 VectorNegate(planes[2], planes[3]);
10839 VectorNegate(planes[4], planes[5]);
10840 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10841 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10842 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10843 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10844 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10845 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10850 matrix4x4_t forwardprojection;
10851 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10852 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10857 float projectionvector[4][3];
10858 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10859 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10860 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10861 projectionvector[0][0] = planes[0][0] * ilocalsize;
10862 projectionvector[0][1] = planes[1][0] * ilocalsize;
10863 projectionvector[0][2] = planes[2][0] * ilocalsize;
10864 projectionvector[1][0] = planes[0][1] * ilocalsize;
10865 projectionvector[1][1] = planes[1][1] * ilocalsize;
10866 projectionvector[1][2] = planes[2][1] * ilocalsize;
10867 projectionvector[2][0] = planes[0][2] * ilocalsize;
10868 projectionvector[2][1] = planes[1][2] * ilocalsize;
10869 projectionvector[2][2] = planes[2][2] * ilocalsize;
10870 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10871 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10872 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10873 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10877 dynamic = model->surfmesh.isanimated;
10878 numsurfacelist = model->nummodelsurfaces;
10879 surfacelist = model->sortedmodelsurfaces;
10880 surfaces = model->data_surfaces;
10883 bih_triangles_count = -1;
10886 if(model->render_bih.numleafs)
10887 bih = &model->render_bih;
10888 else if(model->collision_bih.numleafs)
10889 bih = &model->collision_bih;
10892 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10893 if(bih_triangles_count == 0)
10895 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10897 if(bih_triangles_count > 0)
10899 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10901 surfaceindex = bih_surfaces[triangleindex];
10902 surface = surfaces + surfaceindex;
10903 texture = surface->texture;
10904 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10906 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10908 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10913 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10915 surfaceindex = surfacelist[surfacelistindex];
10916 surface = surfaces + surfaceindex;
10917 // check cull box first because it rejects more than any other check
10918 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10920 // skip transparent surfaces
10921 texture = surface->texture;
10922 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10924 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10926 numtriangles = surface->num_triangles;
10927 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10928 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10933 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10934 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)
10936 int renderentityindex;
10937 float worldmins[3];
10938 float worldmaxs[3];
10939 entity_render_t *ent;
10941 if (!cl_decals_newsystem.integer)
10944 worldmins[0] = worldorigin[0] - worldsize;
10945 worldmins[1] = worldorigin[1] - worldsize;
10946 worldmins[2] = worldorigin[2] - worldsize;
10947 worldmaxs[0] = worldorigin[0] + worldsize;
10948 worldmaxs[1] = worldorigin[1] + worldsize;
10949 worldmaxs[2] = worldorigin[2] + worldsize;
10951 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10953 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10955 ent = r_refdef.scene.entities[renderentityindex];
10956 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10959 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10963 typedef struct r_decalsystem_splatqueue_s
10965 vec3_t worldorigin;
10966 vec3_t worldnormal;
10972 r_decalsystem_splatqueue_t;
10974 int r_decalsystem_numqueued = 0;
10975 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10977 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)
10979 r_decalsystem_splatqueue_t *queue;
10981 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10984 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10985 VectorCopy(worldorigin, queue->worldorigin);
10986 VectorCopy(worldnormal, queue->worldnormal);
10987 Vector4Set(queue->color, r, g, b, a);
10988 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10989 queue->worldsize = worldsize;
10990 queue->decalsequence = cl.decalsequence++;
10993 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10996 r_decalsystem_splatqueue_t *queue;
10998 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10999 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);
11000 r_decalsystem_numqueued = 0;
11003 extern cvar_t cl_decals_max;
11004 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11007 decalsystem_t *decalsystem = &ent->decalsystem;
11014 if (!decalsystem->numdecals)
11017 if (r_showsurfaces.integer)
11020 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11022 R_DecalSystem_Reset(decalsystem);
11026 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11027 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11029 if (decalsystem->lastupdatetime)
11030 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11033 decalsystem->lastupdatetime = r_refdef.scene.time;
11034 decal = decalsystem->decals;
11035 numdecals = decalsystem->numdecals;
11037 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11039 if (decal->color4f[0][3])
11041 decal->lived += frametime;
11042 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11044 memset(decal, 0, sizeof(*decal));
11045 if (decalsystem->freedecal > i)
11046 decalsystem->freedecal = i;
11050 decal = decalsystem->decals;
11051 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11054 // collapse the array by shuffling the tail decals into the gaps
11057 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11058 decalsystem->freedecal++;
11059 if (decalsystem->freedecal == numdecals)
11061 decal[decalsystem->freedecal] = decal[--numdecals];
11064 decalsystem->numdecals = numdecals;
11066 if (numdecals <= 0)
11068 // if there are no decals left, reset decalsystem
11069 R_DecalSystem_Reset(decalsystem);
11073 extern skinframe_t *decalskinframe;
11074 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11077 decalsystem_t *decalsystem = &ent->decalsystem;
11086 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11089 numdecals = decalsystem->numdecals;
11093 if (r_showsurfaces.integer)
11096 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11098 R_DecalSystem_Reset(decalsystem);
11102 // if the model is static it doesn't matter what value we give for
11103 // wantnormals and wanttangents, so this logic uses only rules applicable
11104 // to a model, knowing that they are meaningless otherwise
11105 if (ent == r_refdef.scene.worldentity)
11106 RSurf_ActiveWorldEntity();
11108 RSurf_ActiveModelEntity(ent, false, false, false);
11110 decalsystem->lastupdatetime = r_refdef.scene.time;
11111 decal = decalsystem->decals;
11113 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11115 // update vertex positions for animated models
11116 v3f = decalsystem->vertex3f;
11117 c4f = decalsystem->color4f;
11118 t2f = decalsystem->texcoord2f;
11119 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11121 if (!decal->color4f[0][3])
11124 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11128 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11131 // update color values for fading decals
11132 if (decal->lived >= cl_decals_time.value)
11133 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11137 c4f[ 0] = decal->color4f[0][0] * alpha;
11138 c4f[ 1] = decal->color4f[0][1] * alpha;
11139 c4f[ 2] = decal->color4f[0][2] * alpha;
11141 c4f[ 4] = decal->color4f[1][0] * alpha;
11142 c4f[ 5] = decal->color4f[1][1] * alpha;
11143 c4f[ 6] = decal->color4f[1][2] * alpha;
11145 c4f[ 8] = decal->color4f[2][0] * alpha;
11146 c4f[ 9] = decal->color4f[2][1] * alpha;
11147 c4f[10] = decal->color4f[2][2] * alpha;
11150 t2f[0] = decal->texcoord2f[0][0];
11151 t2f[1] = decal->texcoord2f[0][1];
11152 t2f[2] = decal->texcoord2f[1][0];
11153 t2f[3] = decal->texcoord2f[1][1];
11154 t2f[4] = decal->texcoord2f[2][0];
11155 t2f[5] = decal->texcoord2f[2][1];
11157 // update vertex positions for animated models
11158 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11160 e = rsurface.modelelement3i + 3*decal->triangleindex;
11161 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11162 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11163 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11167 VectorCopy(decal->vertex3f[0], v3f);
11168 VectorCopy(decal->vertex3f[1], v3f + 3);
11169 VectorCopy(decal->vertex3f[2], v3f + 6);
11172 if (r_refdef.fogenabled)
11174 alpha = RSurf_FogVertex(v3f);
11175 VectorScale(c4f, alpha, c4f);
11176 alpha = RSurf_FogVertex(v3f + 3);
11177 VectorScale(c4f + 4, alpha, c4f + 4);
11178 alpha = RSurf_FogVertex(v3f + 6);
11179 VectorScale(c4f + 8, alpha, c4f + 8);
11190 r_refdef.stats.drawndecals += numtris;
11192 // now render the decals all at once
11193 // (this assumes they all use one particle font texture!)
11194 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);
11195 // R_Mesh_ResetTextureState();
11196 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11197 GL_DepthMask(false);
11198 GL_DepthRange(0, 1);
11199 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11200 GL_DepthTest(true);
11201 GL_CullFace(GL_NONE);
11202 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11203 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11204 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11208 static void R_DrawModelDecals(void)
11212 // fade faster when there are too many decals
11213 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11214 for (i = 0;i < r_refdef.scene.numentities;i++)
11215 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11217 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11218 for (i = 0;i < r_refdef.scene.numentities;i++)
11219 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11220 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11222 R_DecalSystem_ApplySplatEntitiesQueue();
11224 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11225 for (i = 0;i < r_refdef.scene.numentities;i++)
11226 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11228 r_refdef.stats.totaldecals += numdecals;
11230 if (r_showsurfaces.integer)
11233 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11235 for (i = 0;i < r_refdef.scene.numentities;i++)
11237 if (!r_refdef.viewcache.entityvisible[i])
11239 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11240 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11244 extern cvar_t mod_collision_bih;
11245 void R_DrawDebugModel(void)
11247 entity_render_t *ent = rsurface.entity;
11248 int i, j, k, l, flagsmask;
11249 const msurface_t *surface;
11250 dp_model_t *model = ent->model;
11253 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11256 if (r_showoverdraw.value > 0)
11258 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11259 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11260 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11261 GL_DepthTest(false);
11262 GL_DepthMask(false);
11263 GL_DepthRange(0, 1);
11264 GL_BlendFunc(GL_ONE, GL_ONE);
11265 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11267 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11269 rsurface.texture = R_GetCurrentTexture(surface->texture);
11270 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11272 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11273 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11274 if (!rsurface.texture->currentlayers->depthmask)
11275 GL_Color(c, 0, 0, 1.0f);
11276 else if (ent == r_refdef.scene.worldentity)
11277 GL_Color(c, c, c, 1.0f);
11279 GL_Color(0, c, 0, 1.0f);
11280 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11284 rsurface.texture = NULL;
11287 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11289 // R_Mesh_ResetTextureState();
11290 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11291 GL_DepthRange(0, 1);
11292 GL_DepthTest(!r_showdisabledepthtest.integer);
11293 GL_DepthMask(false);
11294 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11296 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11300 qboolean cullbox = ent == r_refdef.scene.worldentity;
11301 const q3mbrush_t *brush;
11302 const bih_t *bih = &model->collision_bih;
11303 const bih_leaf_t *bihleaf;
11304 float vertex3f[3][3];
11305 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11307 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11309 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11311 switch (bihleaf->type)
11314 brush = model->brush.data_brushes + bihleaf->itemindex;
11315 if (brush->colbrushf && brush->colbrushf->numtriangles)
11317 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);
11318 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11319 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11322 case BIH_COLLISIONTRIANGLE:
11323 triangleindex = bihleaf->itemindex;
11324 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11325 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11326 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11327 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);
11328 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11329 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11331 case BIH_RENDERTRIANGLE:
11332 triangleindex = bihleaf->itemindex;
11333 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11334 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11335 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11336 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);
11337 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11338 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11344 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11346 if (r_showtris.integer && qglPolygonMode)
11348 if (r_showdisabledepthtest.integer)
11350 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11351 GL_DepthMask(false);
11355 GL_BlendFunc(GL_ONE, GL_ZERO);
11356 GL_DepthMask(true);
11358 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11359 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11361 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11363 rsurface.texture = R_GetCurrentTexture(surface->texture);
11364 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11366 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11367 if (!rsurface.texture->currentlayers->depthmask)
11368 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11369 else if (ent == r_refdef.scene.worldentity)
11370 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11372 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11373 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11377 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11378 rsurface.texture = NULL;
11381 if (r_shownormals.value != 0 && qglBegin)
11383 if (r_showdisabledepthtest.integer)
11385 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11386 GL_DepthMask(false);
11390 GL_BlendFunc(GL_ONE, GL_ZERO);
11391 GL_DepthMask(true);
11393 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11395 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11397 rsurface.texture = R_GetCurrentTexture(surface->texture);
11398 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11400 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11401 qglBegin(GL_LINES);
11402 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11404 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11406 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11407 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11408 qglVertex3f(v[0], v[1], v[2]);
11409 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11410 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11411 qglVertex3f(v[0], v[1], v[2]);
11414 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11416 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11418 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11419 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11420 qglVertex3f(v[0], v[1], v[2]);
11421 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11422 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11423 qglVertex3f(v[0], v[1], v[2]);
11426 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11428 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11430 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11431 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11432 qglVertex3f(v[0], v[1], v[2]);
11433 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11434 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11435 qglVertex3f(v[0], v[1], v[2]);
11438 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11440 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11442 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11443 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11444 qglVertex3f(v[0], v[1], v[2]);
11445 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11446 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11447 qglVertex3f(v[0], v[1], v[2]);
11454 rsurface.texture = NULL;
11458 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11459 int r_maxsurfacelist = 0;
11460 const msurface_t **r_surfacelist = NULL;
11461 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11463 int i, j, endj, flagsmask;
11464 dp_model_t *model = r_refdef.scene.worldmodel;
11465 msurface_t *surfaces;
11466 unsigned char *update;
11467 int numsurfacelist = 0;
11471 if (r_maxsurfacelist < model->num_surfaces)
11473 r_maxsurfacelist = model->num_surfaces;
11475 Mem_Free((msurface_t**)r_surfacelist);
11476 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11479 RSurf_ActiveWorldEntity();
11481 surfaces = model->data_surfaces;
11482 update = model->brushq1.lightmapupdateflags;
11484 // update light styles on this submodel
11485 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11487 model_brush_lightstyleinfo_t *style;
11488 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11490 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11492 int *list = style->surfacelist;
11493 style->value = r_refdef.scene.lightstylevalue[style->style];
11494 for (j = 0;j < style->numsurfaces;j++)
11495 update[list[j]] = true;
11500 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11504 R_DrawDebugModel();
11505 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11509 rsurface.lightmaptexture = NULL;
11510 rsurface.deluxemaptexture = NULL;
11511 rsurface.uselightmaptexture = false;
11512 rsurface.texture = NULL;
11513 rsurface.rtlight = NULL;
11514 numsurfacelist = 0;
11515 // add visible surfaces to draw list
11516 for (i = 0;i < model->nummodelsurfaces;i++)
11518 j = model->sortedmodelsurfaces[i];
11519 if (r_refdef.viewcache.world_surfacevisible[j])
11520 r_surfacelist[numsurfacelist++] = surfaces + j;
11522 // update lightmaps if needed
11523 if (model->brushq1.firstrender)
11525 model->brushq1.firstrender = false;
11526 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11528 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11532 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11533 if (r_refdef.viewcache.world_surfacevisible[j])
11535 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11537 // don't do anything if there were no surfaces
11538 if (!numsurfacelist)
11540 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11543 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11545 // add to stats if desired
11546 if (r_speeds.integer && !skysurfaces && !depthonly)
11548 r_refdef.stats.world_surfaces += numsurfacelist;
11549 for (j = 0;j < numsurfacelist;j++)
11550 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11553 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11556 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11558 int i, j, endj, flagsmask;
11559 dp_model_t *model = ent->model;
11560 msurface_t *surfaces;
11561 unsigned char *update;
11562 int numsurfacelist = 0;
11566 if (r_maxsurfacelist < model->num_surfaces)
11568 r_maxsurfacelist = model->num_surfaces;
11570 Mem_Free((msurface_t **)r_surfacelist);
11571 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11574 // if the model is static it doesn't matter what value we give for
11575 // wantnormals and wanttangents, so this logic uses only rules applicable
11576 // to a model, knowing that they are meaningless otherwise
11577 if (ent == r_refdef.scene.worldentity)
11578 RSurf_ActiveWorldEntity();
11579 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11580 RSurf_ActiveModelEntity(ent, false, false, false);
11582 RSurf_ActiveModelEntity(ent, true, true, true);
11583 else if (depthonly)
11585 switch (vid.renderpath)
11587 case RENDERPATH_GL20:
11588 case RENDERPATH_D3D9:
11589 case RENDERPATH_D3D10:
11590 case RENDERPATH_D3D11:
11591 case RENDERPATH_SOFT:
11592 case RENDERPATH_GLES2:
11593 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11595 case RENDERPATH_GL11:
11596 case RENDERPATH_GL13:
11597 case RENDERPATH_GLES1:
11598 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11604 switch (vid.renderpath)
11606 case RENDERPATH_GL20:
11607 case RENDERPATH_D3D9:
11608 case RENDERPATH_D3D10:
11609 case RENDERPATH_D3D11:
11610 case RENDERPATH_SOFT:
11611 case RENDERPATH_GLES2:
11612 RSurf_ActiveModelEntity(ent, true, true, false);
11614 case RENDERPATH_GL11:
11615 case RENDERPATH_GL13:
11616 case RENDERPATH_GLES1:
11617 RSurf_ActiveModelEntity(ent, true, false, false);
11622 surfaces = model->data_surfaces;
11623 update = model->brushq1.lightmapupdateflags;
11625 // update light styles
11626 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11628 model_brush_lightstyleinfo_t *style;
11629 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11631 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11633 int *list = style->surfacelist;
11634 style->value = r_refdef.scene.lightstylevalue[style->style];
11635 for (j = 0;j < style->numsurfaces;j++)
11636 update[list[j]] = true;
11641 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11645 R_DrawDebugModel();
11646 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11650 rsurface.lightmaptexture = NULL;
11651 rsurface.deluxemaptexture = NULL;
11652 rsurface.uselightmaptexture = false;
11653 rsurface.texture = NULL;
11654 rsurface.rtlight = NULL;
11655 numsurfacelist = 0;
11656 // add visible surfaces to draw list
11657 for (i = 0;i < model->nummodelsurfaces;i++)
11658 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11659 // don't do anything if there were no surfaces
11660 if (!numsurfacelist)
11662 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11665 // update lightmaps if needed
11669 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11674 R_BuildLightMap(ent, surfaces + j);
11679 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11681 R_BuildLightMap(ent, surfaces + j);
11682 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11684 // add to stats if desired
11685 if (r_speeds.integer && !skysurfaces && !depthonly)
11687 r_refdef.stats.entities_surfaces += numsurfacelist;
11688 for (j = 0;j < numsurfacelist;j++)
11689 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11692 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11695 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11697 static texture_t texture;
11698 static msurface_t surface;
11699 const msurface_t *surfacelist = &surface;
11701 // fake enough texture and surface state to render this geometry
11703 texture.update_lastrenderframe = -1; // regenerate this texture
11704 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11705 texture.currentskinframe = skinframe;
11706 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11707 texture.offsetmapping = OFFSETMAPPING_OFF;
11708 texture.offsetscale = 1;
11709 texture.specularscalemod = 1;
11710 texture.specularpowermod = 1;
11712 surface.texture = &texture;
11713 surface.num_triangles = numtriangles;
11714 surface.num_firsttriangle = firsttriangle;
11715 surface.num_vertices = numvertices;
11716 surface.num_firstvertex = firstvertex;
11719 rsurface.texture = R_GetCurrentTexture(surface.texture);
11720 rsurface.lightmaptexture = NULL;
11721 rsurface.deluxemaptexture = NULL;
11722 rsurface.uselightmaptexture = false;
11723 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11726 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)
11728 static msurface_t surface;
11729 const msurface_t *surfacelist = &surface;
11731 // fake enough texture and surface state to render this geometry
11732 surface.texture = texture;
11733 surface.num_triangles = numtriangles;
11734 surface.num_firsttriangle = firsttriangle;
11735 surface.num_vertices = numvertices;
11736 surface.num_firstvertex = firstvertex;
11739 rsurface.texture = R_GetCurrentTexture(surface.texture);
11740 rsurface.lightmaptexture = NULL;
11741 rsurface.deluxemaptexture = NULL;
11742 rsurface.uselightmaptexture = false;
11743 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);